From 58258bc90e755566df79ee8fe3087c8028630f23 Mon Sep 17 00:00:00 2001 From: hjxilinx Date: Fri, 3 Apr 2020 00:16:26 +0800 Subject: [PATCH] [td-97] add express tree serialize and deserilize function and the corresponding unit test cases. --- .gitignore | 1 + src/client/src/tscSQLParser.c | 12 +- src/client/src/tscUtil.c | 2 +- src/query/inc/qast.h | 13 +- src/query/src/qast.c | 126 ++++++- src/query/src/queryExecutor.c | 2 +- src/query/tests/astTest.cpp | 630 ++++++++++++++++++++++++++++++++++ src/util/inc/tbuffer.h | 69 ++-- src/util/src/tbuffer.c | 17 +- src/vnode/tsdb/src/tsdbRead.c | 2 +- 10 files changed, 808 insertions(+), 66 deletions(-) create mode 100644 src/query/tests/astTest.cpp diff --git a/.gitignore b/.gitignore index ba8611030b..f2c1cb75b3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ rpms/ mac/ *.pyc *.tmp +*.swp src/connector/nodejs/node_modules/ src/connector/nodejs/out/ tests/test/ diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 10210917ec..bf186051e8 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -117,7 +117,7 @@ static int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo); static int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo); static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index); -static int32_t tSQLBinaryExprCreateFromSqlExpr(tExprNode **pExpr, tSQLExpr* pAst, int32_t* num, +static int32_t convertSyntaxTreeToExprTree(tExprNode **pExpr, tSQLExpr* pAst, int32_t* num, SColIndexEx** pColIndex, SSqlExprInfo* pExprInfo); /* @@ -1211,9 +1211,9 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel tExprNode* pNode = NULL; SColIndexEx* pColIndex = NULL; - int32_t ret = tSQLBinaryExprCreateFromSqlExpr(&pNode, pItem->pNode, &pBinExprInfo->numOfCols, &pColIndex, &pQueryInfo->exprsInfo); + int32_t ret = convertSyntaxTreeToExprTree(&pNode, pItem->pNode, &pBinExprInfo->numOfCols, &pColIndex, &pQueryInfo->exprsInfo); if (ret != TSDB_CODE_SUCCESS) { - tSQLBinaryExprDestroy(&pNode, NULL); + tExprTreeDestroy(&pNode, NULL); return invalidSqlErrMsg(pQueryInfo->msg, "invalid expression in select clause"); } @@ -5807,20 +5807,20 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { return TSDB_CODE_SUCCESS; // Does not build query message here } -static int32_t tSQLBinaryExprCreateFromSqlExpr(tExprNode **pExpr, tSQLExpr* pAst, int32_t* num, +static int32_t convertSyntaxTreeToExprTree(tExprNode **pExpr, tSQLExpr* pAst, int32_t* num, SColIndexEx** pColIndex, SSqlExprInfo* pExprInfo) { tExprNode* pLeft = NULL; tExprNode* pRight= NULL; if (pAst->pLeft != NULL) { - int32_t ret = tSQLBinaryExprCreateFromSqlExpr(&pLeft, pAst->pLeft, num, pColIndex, pExprInfo); + int32_t ret = convertSyntaxTreeToExprTree(&pLeft, pAst->pLeft, num, pColIndex, pExprInfo); if (ret != TSDB_CODE_SUCCESS) { return ret; } } if (pAst->pRight != NULL) { - int32_t ret = tSQLBinaryExprCreateFromSqlExpr(&pRight, pAst->pRight, num, pColIndex, pExprInfo); + int32_t ret = convertSyntaxTreeToExprTree(&pRight, pAst->pRight, num, pColIndex, pExprInfo); if (ret != TSDB_CODE_SUCCESS) { return ret; } diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index ec6881db3f..d003a72774 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1105,7 +1105,7 @@ void tscClearFieldInfo(SFieldInfo* pFieldInfo) { for(int32_t i = 0; i < pFieldInfo->numOfOutputCols; ++i) { if (pFieldInfo->pExpr[i] != NULL) { - tSQLBinaryExprDestroy(&pFieldInfo->pExpr[i]->binExprInfo.pBinExpr, NULL); + tExprTreeDestroy(&pFieldInfo->pExpr[i]->binExprInfo.pBinExpr, NULL); tfree(pFieldInfo->pExpr[i]->binExprInfo.pReqColumns); tfree(pFieldInfo->pExpr[i]); } diff --git a/src/query/inc/qast.h b/src/query/inc/qast.h index 42ffe6c658..616a2a46af 100644 --- a/src/query/inc/qast.h +++ b/src/query/inc/qast.h @@ -16,6 +16,7 @@ #ifndef TDENGINE_TAST_H #define TDENGINE_TAST_H +#include #ifdef __cplusplus extern "C" { #endif @@ -64,9 +65,9 @@ typedef struct tExprNode { uint8_t nodeType; union { struct { - uint8_t optr; // filter operator - uint8_t hasPK; // 0: do not contain primary filter, 1: contain - void * info; // support filter operation on this expression only available for leaf node + uint8_t optr; // filter operator + uint8_t hasPK; // 0: do not contain primary filter, 1: contain + void * info; // support filter operation on this expression only available for leaf node struct tExprNode *pLeft; // left child pointer struct tExprNode *pRight; // right child pointer @@ -80,7 +81,7 @@ void tSQLBinaryExprFromString(tExprNode **pExpr, SSchema *pSchema, int32_t numOf void tSQLBinaryExprToString(tExprNode *pExpr, char *dst, int32_t *len); -void tSQLBinaryExprDestroy(tExprNode **pExprs, void (*fp)(void*)); +void tExprTreeDestroy(tExprNode **pExprs, void (*fp)(void*)); void tSQLBinaryExprTraverse(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, SBinaryFilterSupp *param); @@ -91,6 +92,10 @@ void tSQLBinaryExprTrv(tExprNode *pExprs, int32_t *val, int16_t *ids); uint8_t getBinaryExprOptr(SSQLToken *pToken); +SBuffer exprTreeToBinary(tExprNode* pExprTree); + +tExprNode* exprTreeFromBinary(const void* pBuf, size_t size); + #ifdef __cplusplus } #endif diff --git a/src/query/src/qast.c b/src/query/src/qast.c index ed45847ea5..4524c5b249 100644 --- a/src/query/src/qast.c +++ b/src/query/src/qast.c @@ -13,10 +13,11 @@ * along with this program. If not, see . */ - #include "os.h" #include "tutil.h" +#include "tbuffer.h" +#include "qast.h" #include "qsqlparser.h" #include "qsyntaxtreefunction.h" #include "taosdef.h" @@ -26,9 +27,7 @@ #include "tstoken.h" #include "ttokendef.h" - #include "../../client/inc/tschemautil.h" -#include "qast.h" #include "tarray.h" #include "tskiplist.h" @@ -246,6 +245,7 @@ static tExprNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *st if (t0.type == TK_RP) { return NULL; } + pLeft = tExprNodeCreate(pSchema, numOfCols, &t0); } @@ -433,24 +433,33 @@ static void tExprNodeDestroy(tExprNode *pNode, void (*fp)(void *)) { } if (pNode->nodeType == TSQL_NODE_EXPR) { - tSQLBinaryExprDestroy(&pNode, fp); + tExprTreeDestroy(&pNode, fp); } else if (pNode->nodeType == TSQL_NODE_VALUE) { tVariantDestroy(pNode->pVal); + } else if (pNode->nodeType == TSQL_NODE_COL) { + free(pNode->pSchema); } free(pNode); } -void tSQLBinaryExprDestroy(tExprNode **pExpr, void (*fp)(void *)) { +void tExprTreeDestroy(tExprNode **pExpr, void (*fp)(void *)) { if (*pExpr == NULL) { return; } - - tExprNodeDestroy((*pExpr)->_node.pLeft, fp); - tExprNodeDestroy((*pExpr)->_node.pRight, fp); - - if (fp != NULL) { - fp((*pExpr)->_node.info); + + if ((*pExpr)->nodeType == TSQL_NODE_EXPR) { + tExprTreeDestroy(&(*pExpr)->_node.pLeft, fp); + tExprTreeDestroy(&(*pExpr)->_node.pRight, fp); + + if (fp != NULL) { + fp((*pExpr)->_node.info); + } + } else if ((*pExpr)->nodeType == TSQL_NODE_VALUE) { + tVariantDestroy((*pExpr)->pVal); + free((*pExpr)->pVal); + } else if ((*pExpr)->nodeType == TSQL_NODE_COL) { + free((*pExpr)->pSchema); } free(*pExpr); @@ -916,3 +925,98 @@ void tSQLBinaryExprTrv(tExprNode *pExprs, int32_t *val, int16_t *ids) { (*val) += 1; } } + +static int32_t exprTreeToBinaryImpl(tExprNode* pExprTree, SBuffer* pBuf) { + tbufWrite(pBuf, &pExprTree->nodeType, sizeof(pExprTree->nodeType)); + + if (pExprTree->nodeType == TSQL_NODE_VALUE) { + tVariant* pVal = pExprTree->pVal; + + tbufWrite(pBuf, &pVal->nType, sizeof(pVal->nType)); + if (pVal->nType == TSDB_DATA_TYPE_BINARY) { + tbufWrite(pBuf, &pVal->nLen, sizeof(pVal->nLen)); + tbufWrite(pBuf, pVal->pz, pVal->nLen); + } else { + tbufWrite(pBuf, &pVal->pz, sizeof(pVal->i64Key)); + } + + } else if (pExprTree->nodeType == TSQL_NODE_COL) { + SSchema* pSchema = pExprTree->pSchema; + tbufWrite(pBuf, &pSchema->colId, sizeof(pSchema->colId)); + tbufWrite(pBuf, &pSchema->bytes, sizeof(pSchema->bytes)); + tbufWrite(pBuf, &pSchema->type, sizeof(pSchema->type)); + + int32_t len = strlen(pSchema->name); + tbufWriteStringLen(pBuf, pSchema->name, len); + + } else if (pExprTree->nodeType == TSQL_NODE_EXPR) { + tbufWrite(pBuf, &pExprTree->_node.optr, sizeof(pExprTree->_node.optr)); + tbufWrite(pBuf, &pExprTree->_node.hasPK, sizeof(pExprTree->_node.hasPK)); + + exprTreeToBinaryImpl(pExprTree->_node.pLeft, pBuf); + exprTreeToBinaryImpl(pExprTree->_node.pRight, pBuf); + } +} + +SBuffer exprTreeToBinary(tExprNode* pExprTree) { + SBuffer buf = {0}; + if (pExprTree == NULL) { + return buf; + } + + int32_t code = tbufBeginWrite(&buf); + if (code != 0) { + return buf; + } + + exprTreeToBinaryImpl(pExprTree, &buf); + return buf; +} + +static tExprNode* exprTreeFromBinaryImpl(tExprNode** pExprTree, SBuffer* pBuf) { + tExprNode* pExpr = calloc(1, sizeof(tExprNode)); + tbufReadToBuffer(pBuf, &pExpr->nodeType, sizeof(pExpr->nodeType)); + + if (pExpr->nodeType == TSQL_NODE_VALUE) { + tVariant* pVal = calloc(1, sizeof(tVariant)); + + tbufReadToBuffer(pBuf, &pVal->nType, sizeof(pVal->nType)); + if (pVal->nType == TSDB_DATA_TYPE_BINARY) { + tbufReadToBuffer(pBuf, &pVal->nLen, sizeof(pVal->nLen)); + pVal->pz = calloc(1, pVal->nLen + 1); + tbufReadToBuffer(pBuf, pVal->pz, pVal->nLen); + } else { + tbufReadToBuffer(pBuf, &pVal->pz, sizeof(pVal->i64Key)); + } + + pExpr->pVal = pVal; + } else if (pExpr->nodeType == TSQL_NODE_COL) { + SSchema* pSchema = calloc(1, sizeof(SSchema)); + tbufReadToBuffer(pBuf, &pSchema->colId, sizeof(pSchema->colId)); + tbufReadToBuffer(pBuf, &pSchema->bytes, sizeof(pSchema->bytes)); + tbufReadToBuffer(pBuf, &pSchema->type, sizeof(pSchema->type)); + + tbufReadToString(pBuf, pSchema->name, TSDB_COL_NAME_LEN); + + pExpr->pSchema = pSchema; + } else if (pExpr->nodeType == TSQL_NODE_EXPR) { + tbufReadToBuffer(pBuf, &pExpr->_node.optr, sizeof(pExpr->_node.optr)); + tbufReadToBuffer(pBuf, &pExpr->_node.hasPK, sizeof(pExpr->_node.hasPK)); + + exprTreeFromBinaryImpl(&pExpr->_node.pLeft, pBuf); + exprTreeFromBinaryImpl(&pExpr->_node.pRight, pBuf); + + assert(pExpr->_node.pLeft != NULL && pExpr->_node.pRight != NULL); + } + + *pExprTree = pExpr; +} + +tExprNode* exprTreeFromBinary(const void* pBuf, size_t size) { + SBuffer rbuf = {0}; + int32_t code = tbufBeginRead(&rbuf, pBuf, size); + + tExprNode* pExprNode = NULL; + exprTreeFromBinaryImpl(&pExprNode, &rbuf); + return pExprNode; +} \ No newline at end of file diff --git a/src/query/src/queryExecutor.c b/src/query/src/queryExecutor.c index d6afe0e40e..75823c4e2e 100644 --- a/src/query/src/queryExecutor.c +++ b/src/query/src/queryExecutor.c @@ -5961,7 +5961,7 @@ static void freeQInfo(SQInfo *pQInfo) { if (pBinExprInfo->numOfCols > 0) { tfree(pBinExprInfo->pReqColumns); - tSQLBinaryExprDestroy(&pBinExprInfo->pBinExpr, NULL); + tExprTreeDestroy(&pBinExprInfo->pBinExpr, NULL); } } diff --git a/src/query/tests/astTest.cpp b/src/query/tests/astTest.cpp new file mode 100644 index 0000000000..ac10cd2429 --- /dev/null +++ b/src/query/tests/astTest.cpp @@ -0,0 +1,630 @@ +#include +#include +#include +#include +#include + +#include "qast.h" +#include "taosmsg.h" +#include "tsdb.h" +#include "tskiplist.h" + +typedef struct ResultObj { + int32_t numOfResult; + char * resultName[64]; +} ResultObj; + +static void initSchema(SSchema *pSchema, int32_t numOfCols); + +static void initSchema_binary(SSchema *schema, int32_t numOfCols); + +static tSkipList *createSkipList(SSchema *pSchema, int32_t numOfTags); +static tSkipList *createSkipList_binary(SSchema *pSchema, int32_t numOfTags); + +static void testQueryStr(SSchema *schema, int32_t numOfCols, char *sql, tSkipList *pSkipList, ResultObj *expectedVal); + +static void dropMeter(tSkipList *pSkipList); + +static void Right2LeftTest(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList); + +static void Left2RightTest(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList); + +static void IllegalExprTest(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList); + +static void Left2RightTest_binary(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList); +static void Right2LeftTest_binary(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList); + +void setValue(ResultObj *pResult, int32_t num, char **val) { + pResult->numOfResult = num; + for (int32_t i = 0; i < num; ++i) { + pResult->resultName[i] = val[i]; + } +} + +static void initSchema_binary(SSchema *schema, int32_t numOfCols) { + schema[0].type = TSDB_DATA_TYPE_BINARY; + schema[0].bytes = 8; + strcpy(schema[0].name, "a"); + + schema[1].type = TSDB_DATA_TYPE_DOUBLE; + schema[1].bytes = 8; + strcpy(schema[1].name, "b"); + + schema[2].type = TSDB_DATA_TYPE_INT; + schema[2].bytes = 20; + strcpy(schema[2].name, "c"); + + schema[3].type = TSDB_DATA_TYPE_BIGINT; + schema[3].bytes = 8; + strcpy(schema[3].name, "d"); + + schema[4].type = TSDB_DATA_TYPE_SMALLINT; + schema[4].bytes = 2; + strcpy(schema[4].name, "e"); + + schema[5].type = TSDB_DATA_TYPE_TINYINT; + schema[5].bytes = 1; + strcpy(schema[5].name, "f"); + + schema[6].type = TSDB_DATA_TYPE_FLOAT; + schema[6].bytes = 4; + strcpy(schema[6].name, "g"); + + schema[7].type = TSDB_DATA_TYPE_BOOL; + schema[7].bytes = 1; + strcpy(schema[7].name, "h"); +} + +static void initSchema(SSchema *schema, int32_t numOfCols) { + schema[0].type = TSDB_DATA_TYPE_INT; + schema[0].bytes = 8; + strcpy(schema[0].name, "a"); + + schema[1].type = TSDB_DATA_TYPE_DOUBLE; + schema[1].bytes = 8; + strcpy(schema[1].name, "b"); + + schema[2].type = TSDB_DATA_TYPE_BINARY; + schema[2].bytes = 20; + strcpy(schema[2].name, "c"); + + schema[3].type = TSDB_DATA_TYPE_BIGINT; + schema[3].bytes = 8; + strcpy(schema[3].name, "d"); + + schema[4].type = TSDB_DATA_TYPE_SMALLINT; + schema[4].bytes = 2; + strcpy(schema[4].name, "e"); + + schema[5].type = TSDB_DATA_TYPE_TINYINT; + schema[5].bytes = 1; + strcpy(schema[5].name, "f"); + + schema[6].type = TSDB_DATA_TYPE_FLOAT; + schema[6].bytes = 4; + strcpy(schema[6].name, "g"); + + schema[7].type = TSDB_DATA_TYPE_BOOL; + schema[7].bytes = 1; + strcpy(schema[7].name, "h"); +} + +// static void addOneNode(SSchema *pSchema, int32_t tagsLen, tSkipList *pSkipList, +// char *meterId, int32_t a, double b, char *c, int64_t d, int16_t e, int8_t f, float g, +// bool h, int32_t numOfTags) { +// STabObj *pMeter = calloc(1, sizeof(STabObj)); +// pMeter->numOfTags = numOfTags; +// pMeter->pTagData = calloc(1, tagsLen + TSDB_METER_ID_LEN); +// strcpy(pMeter->meterId, meterId); +// +// char *tags = pMeter->pTagData + TSDB_METER_ID_LEN; +// int32_t offset = 0; +// +// *(int32_t *) tags = a; +// +// offset += pSchema[0].bytes; +// *(double *) (tags + offset) = b; +// +// offset += pSchema[1].bytes; +// memcpy(tags + offset, c, 3); +// +// offset += pSchema[2].bytes; +// *(int64_t *) (tags + offset) = d; +// +// offset += pSchema[3].bytes; +// *(int16_t *) (tags + offset) = e; +// +// offset += pSchema[4].bytes; +// *(int8_t *) (tags + offset) = f; +// +// offset += pSchema[5].bytes; +// *(float *) (tags + offset) = g; +// +// offset += pSchema[6].bytes; +// *(int8_t *) (tags + offset) = h ? 1 : 0; +// +// tSkipListKey pKey = tSkipListCreateKey(pSchema[0].type, tags, pSchema[0].bytes); +// tSkipListPut(pSkipList, pMeter, &pKey, 1); +//} +// +// static void addOneNode_binary(SSchema *pSchema, int32_t tagsLen, tSkipList *pSkipList, +// char *meterId, int32_t a, double b, char *c, int64_t d, int16_t e, int8_t f, float g, +// bool h, int32_t numOfTags) { +// STabObj *pMeter = calloc(1, sizeof(STabObj)); +// pMeter->numOfTags = numOfTags; +// pMeter->pTagData = calloc(1, tagsLen + TSDB_METER_ID_LEN); +// strcpy(pMeter->meterId, meterId); +// +// char *tags = pMeter->pTagData + TSDB_METER_ID_LEN; +// int32_t offset = 0; +// memcpy(tags, c, pSchema[0].bytes); +// +// offset += pSchema[0].bytes; +// *(double *) (tags + offset) = b; +// +// offset += pSchema[1].bytes; +// *(int32_t *) (tags + offset) = a; +// +// offset += pSchema[2].bytes; +// *(int64_t *) (tags + offset) = d; +// +// offset += pSchema[3].bytes; +// *(int16_t *) (tags + offset) = e; +// +// offset += pSchema[4].bytes; +// *(int8_t *) (tags + offset) = f; +// +// offset += pSchema[5].bytes; +// *(float *) (tags + offset) = g; +// +// offset += pSchema[6].bytes; +// *(int8_t *) (tags + offset) = h ? 1 : 0; +// +// tSkipListKey pKey = tSkipListCreateKey(pSchema[0].type, tags, pSchema[0].bytes); +// tSkipListPut(pSkipList, pMeter, &pKey, 1); +// tSkipListDestroyKey(&pKey); +//} + +// static void dropMeter(tSkipList *pSkipList) { +// tSkipListNode **pRes = NULL; +// int32_t num = tSkipListIterateList(pSkipList, &pRes, NULL, NULL); +// for (int32_t i = 0; i < num; ++i) { +// tSkipListNode *pNode = pRes[i]; +// STabObj *pMeter = (STabObj *) pNode->pData; +// free(pMeter->pTagData); +// free(pMeter); +// pNode->pData = NULL; +// } +// free(pRes); +//} + +// static tSkipList *createSkipList(SSchema *pSchema, int32_t numOfTags) { +// int32_t tagsLen = 0; +// for (int32_t i = 0; i < numOfTags; ++i) { +// tagsLen += pSchema[i].bytes; +// } +// +// tSkipList *pSkipList = tSkipListCreate(10, pSchema[0].type, 4); +// +// addOneNode(pSchema, tagsLen, pSkipList, "tm0\0", 0, 10.5, "abc", 1000, -10000, -20, 1.0, true, 8); +// addOneNode(pSchema, tagsLen, pSkipList, "tm1\0", 1, 20.5, "def", 1100, -10500, -30, 2.0, false, 8); +// addOneNode(pSchema, tagsLen, pSkipList, "tm2\0", 2, 30.5, "ghi", 1200, -11000, -40, 3.0, true, 8); +// addOneNode(pSchema, tagsLen, pSkipList, "tm3\0", 3, 40.5, "jkl", 1300, -11500, -50, 4.0, false, 8); +// addOneNode(pSchema, tagsLen, pSkipList, "tm4\0", 4, 50.5, "mno", 1400, -12000, -60, 5.0, true, 8); +// addOneNode(pSchema, tagsLen, pSkipList, "tm5\0", 5, 60.5, "pqr", 1500, -12500, -70, 6.0, false, 8); +// addOneNode(pSchema, tagsLen, pSkipList, "tm6\0", 6, 70.5, "stu", 1600, -13000, -80, 7.0, true, 8); +// +// return pSkipList; +//} +// +// static tSkipList *createSkipList_binary(SSchema *pSchema, int32_t numOfTags) { +// int32_t tagsLen = 0; +// for (int32_t i = 0; i < numOfTags; ++i) { +// tagsLen += pSchema[i].bytes; +// } +// +// tSkipList *pSkipList = tSkipListCreate(10, pSchema[0].type, 4); +// +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm0\0", 0, 10.5, "abc", 1000, -10000, -20, 1.0, true, 8); +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm1\0", 1, 20.5, "def", 1100, -10500, -30, 2.0, false, 8); +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm2\0", 2, 30.5, "ghi", 1200, -11000, -40, 3.0, true, 8); +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm3\0", 3, 40.5, "jkl", 1300, -11500, -50, 4.0, false, 8); +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm4\0", 4, 50.5, "mno", 1400, -12000, -60, 5.0, true, 8); +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm5\0", 5, 60.5, "pqr", 1500, -12500, -70, 6.0, false, 8); +// addOneNode_binary(pSchema, tagsLen, pSkipList, "tm6\0", 6, 70.5, "stu", 1600, -13000, -80, 7.0, true, 8); +// +// return pSkipList; +//} + +static void testQueryStr(SSchema *schema, int32_t numOfCols, char *sql, tSkipList *pSkipList, ResultObj *pResult) { + tExprNode *pExpr = NULL; + tSQLBinaryExprFromString(&pExpr, schema, numOfCols, sql, strlen(sql)); + + char str[512] = {0}; + int32_t len = 0; + if (pExpr == NULL) { + printf("-----error in parse syntax:%s\n\n", sql); + assert(pResult == NULL); + return; + } + + tSQLBinaryExprToString(pExpr, str, &len); + printf("expr is: %s\n", str); + + SArray *result = NULL; + // tSQLBinaryExprTraverse(pExpr, pSkipList, result, tSkipListNodeFilterCallback, &result); + // printf("the result is:%lld\n", result.num); + // + // bool findResult = false; + // for (int32_t i = 0; i < result.num; ++i) { + // STabObj *pm = (STabObj *)result.pRes[i]; + // printf("meterid:%s,\t", pm->meterId); + // + // for (int32_t j = 0; j < pResult->numOfResult; ++j) { + // if (strcmp(pm->meterId, pResult->resultName[j]) == 0) { + // findResult = true; + // break; + // } + // } + // assert(findResult == true); + // findResult = false; + // } + + printf("\n\n"); + tExprTreeDestroy(&pExpr, NULL); +} + +static void Left2RightTest(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList) { + char str[256] = {0}; + + char *t0[1] = {"tm0"}; + char *t1[1] = {"tm1"}; + char *sql = NULL; + + ResultObj res = {1, {"tm1"}}; + testQueryStr(schema, numOfCols, "a=1", pSkipList, &res); + + char *tt[1] = {"tm6"}; + setValue(&res, 1, tt); + testQueryStr(schema, numOfCols, "a>=6", pSkipList, &res); + + setValue(&res, 1, t0); + testQueryStr(schema, numOfCols, "b<=10.6", pSkipList, &res); + + strcpy(str, "c<>'pqr'"); + char *t2[6] = {"tm0", "tm1", "tm2", "tm3", "tm4", "tm6"}; + setValue(&res, 6, t2); + testQueryStr(schema, numOfCols, str, pSkipList, &res); + + strcpy(str, "c='abc'"); + setValue(&res, 1, t0); + testQueryStr(schema, numOfCols, str, pSkipList, &res); + + char *t3[6] = {"tm1", "tm2", "tm3", "tm4", "tm5", "tm6"}; + setValue(&res, 6, t3); + testQueryStr(schema, numOfCols, "d>1050", pSkipList, &res); + + char *t4[3] = {"tm4", "tm5", "tm6"}; + setValue(&res, 3, t4); + testQueryStr(schema, numOfCols, "g>4.5980765", pSkipList, &res); + + char *t5[4] = {"tm0", "tm2", "tm4", "tm6"}; + setValue(&res, 4, t5); + testQueryStr(schema, numOfCols, "h=true", pSkipList, &res); + + char *t6[3] = {"tm1", "tm3", "tm5"}; + setValue(&res, 3, t6); + testQueryStr(schema, numOfCols, "h=0", pSkipList, &res); + + sql = "(((b<40)))\0"; + char *t7[3] = {"tm0", "tm1", "tm2"}; + setValue(&res, 3, t7); + testQueryStr(schema, numOfCols, sql, pSkipList, &res); + + sql = "((a=1) or (a=10)) or ((b=12))"; + setValue(&res, 1, t1); + testQueryStr(schema, numOfCols, sql, pSkipList, &res); + + sql = "((((((a>0 and a<2))) or a=6) or a=3) or (b=50.5)) and h=0"; + char *t8[2] = {"tm1", "tm3"}; + setValue(&res, 2, t8); + testQueryStr(schema, numOfCols, sql, pSkipList, &res); + + char *tf[1] = {"tm6"}; + setValue(&res, 1, tf); + testQueryStr(schema, numOfCols, "e = -13000", pSkipList, &res); + + char *ft[5] = {"tm0", "tm1", "tm2", "tm3", "tm4"}; + setValue(&res, 5, ft); + testQueryStr(schema, numOfCols, "f > -65", pSkipList, &res); +} + +void Right2LeftTest(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList) { + ResultObj res = {1, {"tm1"}}; + testQueryStr(schema, numOfCols, "((1=a))", pSkipList, &res); + + char *t9[2] = {"tm0", "tm1"}; + setValue(&res, 2, t9); + testQueryStr(schema, numOfCols, "1>=a", pSkipList, &res); + + char *t0[1] = {"tm0"}; + setValue(&res, 1, t0); + testQueryStr(schema, numOfCols, "10.6>=b", pSkipList, &res); + + char *t10[3] = {"tm1", "tm3", "tm5"}; + setValue(&res, 3, t10); + testQueryStr(schema, numOfCols, "0=h", pSkipList, &res); +} + +static void IllegalExprTest(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList) { + testQueryStr(schema, numOfCols, "h=", pSkipList, NULL); + testQueryStr(schema, numOfCols, "h<", pSkipList, NULL); + testQueryStr(schema, numOfCols, "a=1 and ", pSkipList, NULL); + testQueryStr(schema, numOfCols, "and or", pSkipList, NULL); + testQueryStr(schema, numOfCols, "and a = 1 or", pSkipList, NULL); + testQueryStr(schema, numOfCols, "(())", pSkipList, NULL); + testQueryStr(schema, numOfCols, "(", pSkipList, NULL); + testQueryStr(schema, numOfCols, "(a", pSkipList, NULL); + testQueryStr(schema, numOfCols, "(a)", pSkipList, NULL); + testQueryStr(schema, numOfCols, "())", pSkipList, NULL); + testQueryStr(schema, numOfCols, "a===1", pSkipList, NULL); + testQueryStr(schema, numOfCols, "a=1 and ", pSkipList, NULL); +} + +static void Left2RightTest_binary(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList) { + char str[256] = {0}; + char *sql = NULL; + + char *t0[1] = {"tm0"}; + char *t1[1] = {"tm1"}; + + ResultObj res = {1, {"tm0"}}; + strcpy(str, "a='abc'"); + testQueryStr(schema, numOfCols, str, pSkipList, &res); + + char *tt[1] = {"tm6"}; + setValue(&res, 1, tt); + testQueryStr(schema, numOfCols, "c>=6", pSkipList, &res); + + setValue(&res, 1, t0); + testQueryStr(schema, numOfCols, "b<=10.6", pSkipList, &res); + + strcpy(str, "a<>'pqr'"); + char *t2[6] = {"tm0", "tm1", "tm2", "tm3", "tm4", "tm6"}; + setValue(&res, 6, t2); + testQueryStr(schema, numOfCols, str, pSkipList, &res); + + strcpy(str, "a='abc'"); + setValue(&res, 1, t0); + testQueryStr(schema, numOfCols, str, pSkipList, &res); + + char *t3[6] = {"tm1", "tm2", "tm3", "tm4", "tm5", "tm6"}; + setValue(&res, 6, t3); + testQueryStr(schema, numOfCols, "d>1050", pSkipList, &res); + + char *t4[3] = {"tm4", "tm5", "tm6"}; + setValue(&res, 3, t4); + testQueryStr(schema, numOfCols, "g>4.5980765", pSkipList, &res); + + char *t5[4] = {"tm0", "tm2", "tm4", "tm6"}; + setValue(&res, 4, t5); + testQueryStr(schema, numOfCols, "h=true", pSkipList, &res); + + char *t6[3] = {"tm1", "tm3", "tm5"}; + setValue(&res, 3, t6); + testQueryStr(schema, numOfCols, "h=0", pSkipList, &res); + + sql = "(((b<40)))\0"; + char *t7[3] = {"tm0", "tm1", "tm2"}; + setValue(&res, 3, t7); + testQueryStr(schema, numOfCols, sql, pSkipList, &res); + + sql = "((c=1) or (c=10)) or ((b=12))\0"; + setValue(&res, 1, t1); + testQueryStr(schema, numOfCols, sql, pSkipList, &res); + + sql = "((((((c>0 and c<2))) or c=6) or c=3) or (b=50.5)) and h=false\0"; + char *t8[2] = {"tm1", "tm3"}; + setValue(&res, 2, t8); + testQueryStr(schema, numOfCols, sql, pSkipList, &res); +} + +static void Right2LeftTest_binary(SSchema *schema, int32_t numOfCols, tSkipList *pSkipList) { + char str[256] = {0}; + char *sql = NULL; + + char *t0[1] = {"tm0"}; + char *t1[1] = {"tm1"}; + + ResultObj res = {1, {"tm0"}}; + strcpy(str, "'abc'=a"); + testQueryStr(schema, numOfCols, str, pSkipList, &res); + + char *tt[1] = {"tm6"}; + setValue(&res, 1, tt); + testQueryStr(schema, numOfCols, "6<=c", pSkipList, &res); + + setValue(&res, 1, t0); + testQueryStr(schema, numOfCols, "10.6>=b", pSkipList, &res); + + strcpy(str, "'pqr'<>a"); + char *t2[6] = {"tm0", "tm1", "tm2", "tm3", "tm4", "tm6"}; + setValue(&res, 6, t2); + testQueryStr(schema, numOfCols, str, pSkipList, &res); +} + +namespace { +// two level expression tree +tExprNode *createExpr1() { + auto *pLeft = (tExprNode*) calloc(1, sizeof(tExprNode)); + pLeft->nodeType = TSQL_NODE_COL; + pLeft->pSchema = (SSchema*) calloc(1, sizeof(SSchema)); + + strcpy(pLeft->pSchema->name, "col_a"); + pLeft->pSchema->type = TSDB_DATA_TYPE_INT; + pLeft->pSchema->bytes = sizeof(int32_t); + pLeft->pSchema->colId = 1; + + auto *pRight = (tExprNode*) calloc(1, sizeof(tExprNode)); + pRight->nodeType = TSQL_NODE_VALUE; + pRight->pVal = (tVariant*) calloc(1, sizeof(tVariant)); + + pRight->pVal->nType = TSDB_DATA_TYPE_INT; + pRight->pVal->i64Key = 12; + + auto *pRoot = (tExprNode*) calloc(1, sizeof(tExprNode)); + pRoot->nodeType = TSQL_NODE_EXPR; + + pRoot->_node.optr = TSDB_RELATION_EQUAL; + pRoot->_node.pLeft = pLeft; + pRoot->_node.pRight = pRight; + pRoot->_node.hasPK = true; + + return pRoot; +} + +// thress level expression tree +tExprNode* createExpr2() { + auto *pLeft2 = (tExprNode*) calloc(1, sizeof(tExprNode)); + pLeft2->nodeType = TSQL_NODE_COL; + pLeft2->pSchema = (SSchema*) calloc(1, sizeof(SSchema)); + + strcpy(pLeft2->pSchema->name, "col_a"); + pLeft2->pSchema->type = TSDB_DATA_TYPE_BINARY; + pLeft2->pSchema->bytes = 20; + pLeft2->pSchema->colId = 1; + + auto *pRight2 = (tExprNode*) calloc(1, sizeof(tExprNode)); + pRight2->nodeType = TSQL_NODE_VALUE; + pRight2->pVal = (tVariant*) calloc(1, sizeof(tVariant)); + + pRight2->pVal->nType = TSDB_DATA_TYPE_BINARY; + const char* v = "hello world!"; + pRight2->pVal->pz = strdup(v); + pRight2->pVal->nLen = strlen(v); + + auto *p1 = (tExprNode*) calloc(1, sizeof(tExprNode)); + p1->nodeType = TSQL_NODE_EXPR; + + p1->_node.optr = TSDB_RELATION_LIKE; + p1->_node.pLeft = pLeft2; + p1->_node.pRight = pRight2; + p1->_node.hasPK = false; + + auto *pLeft1 = (tExprNode*) calloc(1, sizeof(tExprNode)); + pLeft1->nodeType = TSQL_NODE_COL; + pLeft1->pSchema = (SSchema*) calloc(1, sizeof(SSchema)); + + strcpy(pLeft1->pSchema->name, "col_b"); + pLeft1->pSchema->type = TSDB_DATA_TYPE_DOUBLE; + pLeft1->pSchema->bytes = 8; + pLeft1->pSchema->colId = 99; + + auto *pRight1 = (tExprNode*) calloc(1, sizeof(tExprNode)); + pRight1->nodeType = TSQL_NODE_VALUE; + pRight1->pVal = (tVariant*) calloc(1, sizeof(tVariant)); + + pRight1->pVal->nType = TSDB_DATA_TYPE_DOUBLE; + pRight1->pVal->dKey = 91.99; + + auto *p2 = (tExprNode*) calloc(1, sizeof(tExprNode)); + p2->nodeType = TSQL_NODE_EXPR; + + p2->_node.optr = TSDB_RELATION_LARGE_EQUAL; + p2->_node.pLeft = pLeft1; + p2->_node.pRight = pRight1; + p2->_node.hasPK = false; + + auto *pRoot = (tExprNode*) calloc(1, sizeof(tExprNode)); + pRoot->nodeType = TSQL_NODE_EXPR; + + pRoot->_node.optr = TSDB_RELATION_OR; + pRoot->_node.pLeft = p1; + pRoot->_node.pRight = p2; + pRoot->_node.hasPK = true; + return pRoot; +} + +void exprSerializeTest1() { + tExprNode* p1 = createExpr1(); + SBuffer buf = exprTreeToBinary(p1); + + size_t size = tbufTell(&buf); + ASSERT_TRUE(size > 0); + char* b = tbufGetData(&buf, false); + + tExprNode* p2 = exprTreeFromBinary(b, size); + ASSERT_EQ(p1->nodeType, p2->nodeType); + + ASSERT_EQ(p2->_node.optr, p1->_node.optr); + ASSERT_EQ(p2->_node.pLeft->nodeType, p1->_node.pLeft->nodeType); + ASSERT_EQ(p2->_node.pRight->nodeType, p1->_node.pRight->nodeType); + + SSchema* s1 = p1->_node.pLeft->pSchema; + SSchema* s2 = p2->_node.pLeft->pSchema; + + ASSERT_EQ(s2->colId, s1->colId); + ASSERT_EQ(s2->type, s1->type); + ASSERT_EQ(s2->bytes, s1->bytes); + ASSERT_STRCASEEQ(s2->name, s1->name); + + tVariant* v1 = p1->_node.pRight->pVal; + tVariant* v2 = p2->_node.pRight->pVal; + + ASSERT_EQ(v1->nType, v2->nType); + ASSERT_EQ(v1->i64Key, v2->i64Key); + ASSERT_EQ(p1->_node.hasPK, p2->_node.hasPK); + + tExprTreeDestroy(&p1, nullptr); + tExprTreeDestroy(&p2, nullptr); + + tbufClose(&buf, false); +} + +void exprSerializeTest2() { + tExprNode* p1 = createExpr2(); + SBuffer buf = exprTreeToBinary(p1); + + size_t size = tbufTell(&buf); + ASSERT_TRUE(size > 0); + char* b = tbufGetData(&buf, false); + + tExprNode* p2 = exprTreeFromBinary(b, size); + ASSERT_EQ(p1->nodeType, p2->nodeType); + + ASSERT_EQ(p2->_node.optr, p1->_node.optr); + ASSERT_EQ(p2->_node.pLeft->nodeType, p1->_node.pLeft->nodeType); + ASSERT_EQ(p2->_node.pRight->nodeType, p1->_node.pRight->nodeType); + + tExprNode* c1Left = p1->_node.pLeft; + tExprNode* c2Left = p2->_node.pLeft; + + ASSERT_EQ(c1Left->nodeType, c2Left->nodeType); + + ASSERT_EQ(c2Left->nodeType, TSQL_NODE_EXPR); + ASSERT_EQ(c2Left->_node.optr, TSDB_RELATION_LIKE); + + ASSERT_STRCASEEQ(c2Left->_node.pLeft->pSchema->name, "col_a"); + ASSERT_EQ(c2Left->_node.pRight->nodeType, TSQL_NODE_VALUE); + + ASSERT_STRCASEEQ(c2Left->_node.pRight->pVal->pz, "hello world!"); + + tExprNode* c1Right = p1->_node.pRight; + tExprNode* c2Right = p2->_node.pRight; + + ASSERT_EQ(c1Right->nodeType, c2Right->nodeType); + ASSERT_EQ(c2Right->nodeType, TSQL_NODE_EXPR); + ASSERT_EQ(c2Right->_node.optr, TSDB_RELATION_LARGE_EQUAL); + ASSERT_EQ(c2Right->_node.pRight->pVal->dKey, 91.99); + + ASSERT_EQ(p2->_node.hasPK, true); + + tExprTreeDestroy(&p1, nullptr); + tExprTreeDestroy(&p2, nullptr); + + tbufClose(&buf, false); +} +} // namespace +TEST(testCase, astTest) { + exprSerializeTest2(); +} \ No newline at end of file diff --git a/src/util/inc/tbuffer.h b/src/util/inc/tbuffer.h index 9dc6d97eb6..d52031fc6a 100644 --- a/src/util/inc/tbuffer.h +++ b/src/util/inc/tbuffer.h @@ -13,14 +13,15 @@ * along with this program. If not, see . */ -#include -#include -#include -#include - #ifndef TDENGINE_TBUFFER_H #define TDENGINE_TBUFFER_H +#include "setjmp.h" +#include "os.h" + +#ifdef __cplusplus +extern "C" { +#endif /* SBuffer can be used to read or write a buffer, but cannot be used for both @@ -80,37 +81,33 @@ int main(int argc, char** argv) { */ typedef struct { jmp_buf jb; - char* data; - size_t pos; - size_t size; + char* data; + size_t pos; + size_t size; } SBuffer; - // common functions can be used in both read & write #define tbufThrowError(buf, code) longjmp((buf)->jb, (code)) size_t tbufTell(SBuffer* buf); size_t tbufSeekTo(SBuffer* buf, size_t pos); size_t tbufSkip(SBuffer* buf, size_t size); -void tbufClose(SBuffer* buf, bool keepData); - +void tbufClose(SBuffer* buf, bool keepData); // basic read functions -#define tbufBeginRead(buf, data, len) (((buf)->data = (char*)data), ((buf)->pos = 0), ((buf)->size = ((data) == NULL) ? 0 : (len)), setjmp((buf)->jb)) -char* tbufRead(SBuffer* buf, size_t size); -void tbufReadToBuffer(SBuffer* buf, void* dst, size_t size); +#define tbufBeginRead(buf, _data, len) ((buf)->data = (char*)(_data), ((buf)->pos = 0), ((buf)->size = ((_data) == NULL) ? 0 : (len)), setjmp((buf)->jb)) +char* tbufRead(SBuffer* buf, size_t size); +void tbufReadToBuffer(SBuffer* buf, void* dst, size_t size); const char* tbufReadString(SBuffer* buf, size_t* len); -size_t tbufReadToString(SBuffer* buf, char* dst, size_t size); - +size_t tbufReadToString(SBuffer* buf, char* dst, size_t size); // basic write functions #define tbufBeginWrite(buf) ((buf)->data = NULL, ((buf)->pos = 0), ((buf)->size = 0), setjmp((buf)->jb)) -void tbufEnsureCapacity(SBuffer* buf, size_t size); +void tbufEnsureCapacity(SBuffer* buf, size_t size); char* tbufGetData(SBuffer* buf, bool takeOver); -void tbufWrite(SBuffer* buf, const void* data, size_t size); -void tbufWriteAt(SBuffer* buf, size_t pos, const void* data, size_t size); -void tbufWriteStringLen(SBuffer* buf, const char* str, size_t len); -void tbufWriteString(SBuffer* buf, const char* str); - +void tbufWrite(SBuffer* buf, const void* data, size_t size); +void tbufWriteAt(SBuffer* buf, size_t pos, const void* data, size_t size); +void tbufWriteStringLen(SBuffer* buf, const char* str, size_t len); +void tbufWriteString(SBuffer* buf, const char* str); // read & write function for primitive types #ifndef TBUFFER_DEFINE_FUNCTION @@ -120,17 +117,21 @@ void tbufWriteString(SBuffer* buf, const char* str); void tbufWrite##name##At(SBuffer* buf, size_t pos, type data); #endif -TBUFFER_DEFINE_FUNCTION( bool, Bool ) -TBUFFER_DEFINE_FUNCTION( char, Char ) -TBUFFER_DEFINE_FUNCTION( int8_t, Int8 ) -TBUFFER_DEFINE_FUNCTION( uint8_t, Unt8 ) -TBUFFER_DEFINE_FUNCTION( int16_t, Int16 ) -TBUFFER_DEFINE_FUNCTION( uint16_t, Uint16 ) -TBUFFER_DEFINE_FUNCTION( int32_t, Int32 ) -TBUFFER_DEFINE_FUNCTION( uint32_t, Uint32 ) -TBUFFER_DEFINE_FUNCTION( int64_t, Int64 ) -TBUFFER_DEFINE_FUNCTION( uint64_t, Uint64 ) -TBUFFER_DEFINE_FUNCTION( float, Float ) -TBUFFER_DEFINE_FUNCTION( double, Double ) +TBUFFER_DEFINE_FUNCTION(bool, Bool) +TBUFFER_DEFINE_FUNCTION(char, Char) +TBUFFER_DEFINE_FUNCTION(int8_t, Int8) +TBUFFER_DEFINE_FUNCTION(uint8_t, Unt8) +TBUFFER_DEFINE_FUNCTION(int16_t, Int16) +TBUFFER_DEFINE_FUNCTION(uint16_t, Uint16) +TBUFFER_DEFINE_FUNCTION(int32_t, Int32) +TBUFFER_DEFINE_FUNCTION(uint32_t, Uint32) +TBUFFER_DEFINE_FUNCTION(int64_t, Int64) +TBUFFER_DEFINE_FUNCTION(uint64_t, Uint64) +TBUFFER_DEFINE_FUNCTION(float, Float) +TBUFFER_DEFINE_FUNCTION(double, Double) + +#ifdef __cplusplus +} +#endif #endif \ No newline at end of file diff --git a/src/util/src/tbuffer.c b/src/util/src/tbuffer.c index ac7d22078d..a83d7dddb0 100644 --- a/src/util/src/tbuffer.c +++ b/src/util/src/tbuffer.c @@ -30,7 +30,7 @@ tbufWriteAt(buf, pos, &data, sizeof(data));\ } -#include "../inc/tbuffer.h" +#include "tbuffer.h" //////////////////////////////////////////////////////////////////////////////// @@ -119,13 +119,14 @@ void tbufEnsureCapacity(SBuffer* buf, size_t size) { } char* tbufGetData(SBuffer* buf, bool takeOver) { - char* ret = buf->data; - if (takeOver) { - buf->pos = 0; - buf->size = 0; - buf->data = NULL; - } - return ret; + char* ret = buf->data; + if (takeOver) { + buf->pos = 0; + buf->size = 0; + buf->data = NULL; + } + + return ret; } void tbufEndWrite(SBuffer* buf) { diff --git a/src/vnode/tsdb/src/tsdbRead.c b/src/vnode/tsdb/src/tsdbRead.c index 806d004f69..c134ba257a 100644 --- a/src/vnode/tsdb/src/tsdbRead.c +++ b/src/vnode/tsdb/src/tsdbRead.c @@ -1310,7 +1310,7 @@ static int32_t doQueryTableList(STable* pSTable, SArray* pRes, const char* pCond }; tSQLBinaryExprTraverse(pExpr, pSTable->pIndex, pRes, &supp); - tSQLBinaryExprDestroy(&pExpr, tSQLListTraverseDestroyInfo); + tExprTreeDestroy(&pExpr, tSQLListTraverseDestroyInfo); tansformQueryResult(pRes); -- GitLab