TD-97: search in array is done
This commit is contained in:
parent
de50a2d704
commit
87363383f9
|
@ -32,6 +32,20 @@ extern "C" {
|
||||||
#define TSKEY int64_t
|
#define TSKEY int64_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Data type definition
|
||||||
|
#define TSDB_DATA_TYPE_NULL 0 // 1 bytes
|
||||||
|
#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes
|
||||||
|
#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte
|
||||||
|
#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes
|
||||||
|
#define TSDB_DATA_TYPE_INT 4 // 4 bytes
|
||||||
|
#define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes
|
||||||
|
#define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes
|
||||||
|
#define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes
|
||||||
|
#define TSDB_DATA_TYPE_BINARY 8 // string
|
||||||
|
#define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes
|
||||||
|
#define TSDB_DATA_TYPE_NCHAR 10 // unicode string
|
||||||
|
#define TSDB_DATA_TYPE_ARRAY 11 // only used 'in' query to hold the values
|
||||||
|
|
||||||
// Bytes for each type.
|
// Bytes for each type.
|
||||||
extern const int32_t TYPE_BYTES[11];
|
extern const int32_t TYPE_BYTES[11];
|
||||||
// TODO: replace and remove code below
|
// TODO: replace and remove code below
|
||||||
|
|
|
@ -35,7 +35,6 @@ enum {
|
||||||
TSQL_NODE_EXPR = 0x1,
|
TSQL_NODE_EXPR = 0x1,
|
||||||
TSQL_NODE_COL = 0x2,
|
TSQL_NODE_COL = 0x2,
|
||||||
TSQL_NODE_VALUE = 0x4,
|
TSQL_NODE_VALUE = 0x4,
|
||||||
TSQL_NODE_ARRAY = 0x8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef bool (*__result_filter_fn_t)(const void *, void *);
|
typedef bool (*__result_filter_fn_t)(const void *, void *);
|
||||||
|
@ -71,7 +70,6 @@ typedef struct tExprNode {
|
||||||
struct tExprNode *pRight; // right child pointer
|
struct tExprNode *pRight; // right child pointer
|
||||||
} _node;
|
} _node;
|
||||||
struct SSchema *pSchema;
|
struct SSchema *pSchema;
|
||||||
SArray* array;
|
|
||||||
tVariant * pVal;
|
tVariant * pVal;
|
||||||
};
|
};
|
||||||
} tExprNode;
|
} tExprNode;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define TDENGINE_TVARIANT_H
|
#define TDENGINE_TVARIANT_H
|
||||||
|
|
||||||
#include "tstoken.h"
|
#include "tstoken.h"
|
||||||
|
#include "tarray.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -31,6 +32,7 @@ typedef struct tVariant {
|
||||||
double dKey;
|
double dKey;
|
||||||
char * pz;
|
char * pz;
|
||||||
wchar_t *wpz;
|
wchar_t *wpz;
|
||||||
|
SArray *arr; // only for 'in' query to hold value list, not value for a field
|
||||||
};
|
};
|
||||||
} tVariant;
|
} tVariant;
|
||||||
|
|
||||||
|
|
|
@ -460,9 +460,6 @@ void tExprTreeDestroy(tExprNode **pExpr, void (*fp)(void *)) {
|
||||||
free((*pExpr)->pVal);
|
free((*pExpr)->pVal);
|
||||||
} else if ((*pExpr)->nodeType == TSQL_NODE_COL) {
|
} else if ((*pExpr)->nodeType == TSQL_NODE_COL) {
|
||||||
free((*pExpr)->pSchema);
|
free((*pExpr)->pSchema);
|
||||||
} else if ((*pExpr)->nodeType == TSQL_NODE_ARRAY) {
|
|
||||||
// BUGBUG: memory leak, need free elements in the array
|
|
||||||
taosArrayDestroy((*pExpr)->array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(*pExpr);
|
free(*pExpr);
|
||||||
|
@ -524,38 +521,48 @@ static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
|
||||||
if (optr == TSDB_RELATION_GREATER || optr == TSDB_RELATION_GREATER_EQUAL ||
|
if (optr == TSDB_RELATION_GREATER || optr == TSDB_RELATION_GREATER_EQUAL ||
|
||||||
optr == TSDB_RELATION_EQUAL || optr == TSDB_RELATION_NOT_EQUAL) {
|
optr == TSDB_RELATION_EQUAL || optr == TSDB_RELATION_NOT_EQUAL) {
|
||||||
pCond->start = calloc(1, sizeof(tVariant));
|
pCond->start = calloc(1, sizeof(tVariant));
|
||||||
|
|
||||||
tVariantAssign(&pCond->start->v, &queryColInfo->q);
|
tVariantAssign(&pCond->start->v, &queryColInfo->q);
|
||||||
pCond->start->optr = queryColInfo->optr;
|
pCond->start->optr = queryColInfo->optr;
|
||||||
|
|
||||||
} else if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
|
} else if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
|
||||||
pCond->end = calloc(1, sizeof(tVariant));
|
pCond->end = calloc(1, sizeof(tVariant));
|
||||||
|
|
||||||
tVariantAssign(&pCond->end->v, &queryColInfo->q);
|
tVariantAssign(&pCond->end->v, &queryColInfo->q);
|
||||||
pCond->end->optr = queryColInfo->optr;
|
pCond->end->optr = queryColInfo->optr;
|
||||||
|
|
||||||
|
} else if (optr == TSDB_RELATION_IN) {
|
||||||
|
printf("relation is in\n");
|
||||||
|
|
||||||
|
} else if (optr == TSDB_RELATION_LIKE) {
|
||||||
|
printf("relation is like\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tQueryOnSkipList(SSkipList* pSkipList, SQueryCond* pCond, int32_t type, SArray* result) {
|
static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArray* result) {
|
||||||
SSkipListIterator* iter = NULL;
|
SSkipListIterator* iter = NULL;
|
||||||
|
int32_t type = pQueryInfo->q.nType;
|
||||||
if (pCond->start != NULL) {
|
|
||||||
iter = tSkipListCreateIterFromVal(pSkipList, (char*) &pCond->start->v.i64Key, type, TSDB_ORDER_ASC);
|
SQueryCond cond = { 0 };
|
||||||
|
setQueryCond(pQueryInfo, &cond);
|
||||||
|
|
||||||
|
if (cond.start != NULL) {
|
||||||
|
iter = tSkipListCreateIterFromVal(pSkipList, (char*) &cond.start->v.i64Key, type, TSDB_ORDER_ASC);
|
||||||
} else {
|
} else {
|
||||||
iter = tSkipListCreateIterFromVal(pSkipList, (char*) &pCond->end->v.i64Key, type, TSDB_ORDER_DESC);
|
iter = tSkipListCreateIterFromVal(pSkipList, (char*) &cond.end->v.i64Key, type, TSDB_ORDER_DESC);
|
||||||
}
|
}
|
||||||
|
|
||||||
__compar_fn_t func = getComparFunc(pSkipList->keyInfo.type, type, 0);
|
__compar_fn_t func = getComparFunc(pSkipList->keyInfo.type, type, 0);
|
||||||
|
|
||||||
if (pCond->start != NULL) {
|
if (cond.start != NULL) {
|
||||||
int32_t optr = pCond->start->optr;
|
int32_t optr = cond.start->optr;
|
||||||
|
|
||||||
if (optr == TSDB_RELATION_EQUAL) {
|
if (optr == TSDB_RELATION_EQUAL) {
|
||||||
while(tSkipListIterNext(iter)) {
|
while(tSkipListIterNext(iter)) {
|
||||||
SSkipListNode* pNode = tSkipListIterGet(iter);
|
SSkipListNode* pNode = tSkipListIterGet(iter);
|
||||||
|
|
||||||
int32_t ret = func(SL_GET_NODE_KEY(pSkipList, pNode), &pCond->start->v.i64Key);
|
int32_t ret = func(SL_GET_NODE_KEY(pSkipList, pNode), &cond.start->v.i64Key);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
taosArrayPush(result, SL_GET_NODE_DATA(pNode));
|
taosArrayPush(result, SL_GET_NODE_DATA(pNode));
|
||||||
} else {
|
} else {
|
||||||
|
@ -570,7 +577,7 @@ static void tQueryOnSkipList(SSkipList* pSkipList, SQueryCond* pCond, int32_t ty
|
||||||
SSkipListNode* pNode = tSkipListIterGet(iter);
|
SSkipListNode* pNode = tSkipListIterGet(iter);
|
||||||
|
|
||||||
if (comp) {
|
if (comp) {
|
||||||
ret = func(SL_GET_NODE_KEY(pSkipList, pNode), &pCond->start->v.i64Key);
|
ret = func(SL_GET_NODE_KEY(pSkipList, pNode), &cond.start->v.i64Key);
|
||||||
assert(ret >= 0);
|
assert(ret >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +594,7 @@ static void tQueryOnSkipList(SSkipList* pSkipList, SQueryCond* pCond, int32_t ty
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int32_t optr = pCond->end->optr;
|
int32_t optr = cond.end->optr;
|
||||||
|
|
||||||
if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
|
if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
|
||||||
bool comp = true;
|
bool comp = true;
|
||||||
|
@ -597,7 +604,7 @@ static void tQueryOnSkipList(SSkipList* pSkipList, SQueryCond* pCond, int32_t ty
|
||||||
SSkipListNode* pNode = tSkipListIterGet(iter);
|
SSkipListNode* pNode = tSkipListIterGet(iter);
|
||||||
|
|
||||||
if (comp) {
|
if (comp) {
|
||||||
ret = func(SL_GET_NODE_KEY(pSkipList, pNode), &pCond->end->v.i64Key);
|
ret = func(SL_GET_NODE_KEY(pSkipList, pNode), &cond.end->v.i64Key);
|
||||||
assert(ret <= 0);
|
assert(ret <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,6 +795,36 @@ static void tSQLBinaryTraverseOnSkipList(tExprNode *pExpr, SArray *pResult, SSki
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <tsdbMain.h>
|
||||||
|
|
||||||
|
static void tQueryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArray* result) {
|
||||||
|
SSkipListIterator* iter = tSkipListCreateIter(pSkipList);
|
||||||
|
|
||||||
|
while (tSkipListIterNext(iter)) {
|
||||||
|
bool addToResult = false;
|
||||||
|
|
||||||
|
SSkipListNode *pNode = tSkipListIterGet(iter);
|
||||||
|
STable* table = *(STable**) SL_GET_NODE_DATA(pNode);
|
||||||
|
|
||||||
|
if (pQueryInfo->colIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||||
|
if (pQueryInfo->optr == TSDB_RELATION_IN) {
|
||||||
|
addToResult = pQueryInfo->compare(table->name, pQueryInfo->q.arr);
|
||||||
|
} else if(pQueryInfo->optr == TSDB_RELATION_LIKE) {
|
||||||
|
addToResult = pQueryInfo->compare(table->name, pQueryInfo->q.pz);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: other columns
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addToResult) {
|
||||||
|
taosArrayPush(result, table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// post-root order traverse syntax tree
|
// post-root order traverse syntax tree
|
||||||
void tExprTreeTraverse(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, SBinaryFilterSupp *param) {
|
void tExprTreeTraverse(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, SBinaryFilterSupp *param) {
|
||||||
if (pExpr == NULL) {
|
if (pExpr == NULL) {
|
||||||
|
@ -797,95 +834,99 @@ void tExprTreeTraverse(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, S
|
||||||
tExprNode *pLeft = pExpr->_node.pLeft;
|
tExprNode *pLeft = pExpr->_node.pLeft;
|
||||||
tExprNode *pRight = pExpr->_node.pRight;
|
tExprNode *pRight = pExpr->_node.pRight;
|
||||||
|
|
||||||
// recursive traverse left child branch
|
// column project
|
||||||
if (pLeft->nodeType == TSQL_NODE_EXPR || pRight->nodeType == TSQL_NODE_EXPR) {
|
if (pLeft->nodeType != TSQL_NODE_EXPR && pRight->nodeType != TSQL_NODE_EXPR) {
|
||||||
uint8_t weight = pLeft->_node.hasPK + pRight->_node.hasPK;
|
assert(pLeft->nodeType == TSQL_NODE_COL && pRight->nodeType == TSQL_NODE_VALUE);
|
||||||
|
|
||||||
if (weight == 0 && taosArrayGetSize(result) > 0 && pSkipList == NULL) {
|
param->setupInfoFn(pExpr, param->pExtInfo);
|
||||||
/**
|
if (pSkipList == NULL) {
|
||||||
* Perform the filter operation based on the initial filter result, which is obtained from filtering from index.
|
tSQLListTraverseOnResult(pExpr, param->fp, result);
|
||||||
* Since no index presented, the filter operation is done by scan all elements in the result set.
|
return;
|
||||||
*
|
}
|
||||||
* if the query is a high selectivity filter, only small portion of meters are retrieved.
|
|
||||||
*/
|
tQueryInfo *pQueryInfo = pExpr->_node.info;
|
||||||
|
if (pQueryInfo->colIndex == 0 && pQueryInfo->optr != TSDB_RELATION_LIKE) {
|
||||||
|
tQueryIndexColumn(pSkipList, pQueryInfo, result);
|
||||||
|
} else {
|
||||||
|
tQueryIndexlessColumn(pSkipList, pQueryInfo, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursive traverse left child branch
|
||||||
|
uint8_t weight = pLeft->_node.hasPK + pRight->_node.hasPK;
|
||||||
|
|
||||||
|
if (weight == 0 ) {
|
||||||
|
if (taosArrayGetSize(result) > 0 && pSkipList == NULL) {
|
||||||
|
/**
|
||||||
|
* Perform the filter operation based on the initial filter result, which is obtained from filtering from index.
|
||||||
|
* Since no index presented, the filter operation is done by scan all elements in the result set.
|
||||||
|
*
|
||||||
|
* if the query is a high selectivity filter, only small portion of meters are retrieved.
|
||||||
|
*/
|
||||||
exprTreeTraverseImpl(pExpr, result, param);
|
exprTreeTraverseImpl(pExpr, result, param);
|
||||||
} else if (weight == 0) {
|
} else {
|
||||||
/**
|
/**
|
||||||
* apply the hierarchical expression to every node in skiplist for find the qualified nodes
|
* apply the hierarchical expression to every node in skiplist for find the qualified nodes
|
||||||
*/
|
*/
|
||||||
assert(taosArrayGetSize(result) == 0);
|
assert(taosArrayGetSize(result) == 0);
|
||||||
tSQLBinaryTraverseOnSkipList(pExpr, result, pSkipList, param);
|
tSQLBinaryTraverseOnSkipList(pExpr, result, pSkipList, param);
|
||||||
} else if (weight == 2 || (weight == 1 && pExpr->_node.optr == TSDB_RELATION_OR)) {
|
|
||||||
SArray* rLeft = taosArrayInit(10, POINTER_BYTES);
|
|
||||||
SArray* rRight = taosArrayInit(10, POINTER_BYTES);
|
|
||||||
|
|
||||||
tExprTreeTraverse(pLeft, pSkipList, rLeft, param);
|
|
||||||
tExprTreeTraverse(pRight, pSkipList, rRight, param);
|
|
||||||
|
|
||||||
if (pExpr->_node.optr == TSDB_RELATION_AND) { // CROSS
|
|
||||||
intersect(rLeft, rRight, result);
|
|
||||||
} else if (pExpr->_node.optr == TSDB_RELATION_OR) { // or
|
|
||||||
merge(rLeft, rRight, result);
|
|
||||||
} else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayDestroy(rLeft);
|
|
||||||
taosArrayDestroy(rRight);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* (weight == 1 && pExpr->nSQLBinaryOptr == TSDB_RELATION_AND) is handled here
|
|
||||||
*
|
|
||||||
* first, we filter results based on the skiplist index, which is the initial filter stage,
|
|
||||||
* then, we conduct the secondary filter operation based on the result from the initial filter stage.
|
|
||||||
*/
|
|
||||||
assert(pExpr->_node.optr == TSDB_RELATION_AND);
|
|
||||||
|
|
||||||
tExprNode *pFirst = NULL;
|
|
||||||
tExprNode *pSecond = NULL;
|
|
||||||
if (pLeft->_node.hasPK == 1) {
|
|
||||||
pFirst = pLeft;
|
|
||||||
pSecond = pRight;
|
|
||||||
} else {
|
|
||||||
pFirst = pRight;
|
|
||||||
pSecond = pLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(pFirst != pSecond && pFirst != NULL && pSecond != NULL);
|
|
||||||
|
|
||||||
// we filter the result based on the skiplist index in the first place
|
|
||||||
tExprTreeTraverse(pFirst, pSkipList, result, param);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* recursively perform the filter operation based on the initial results,
|
|
||||||
* So, we do not set the skip list index as a parameter
|
|
||||||
*/
|
|
||||||
tExprTreeTraverse(pSecond, NULL, result, param);
|
|
||||||
}
|
|
||||||
} else { // column project
|
|
||||||
assert(pLeft->nodeType == TSQL_NODE_COL && (pRight->nodeType == TSQL_NODE_VALUE || pRight->nodeType == TSQL_NODE_ARRAY));
|
|
||||||
|
|
||||||
param->setupInfoFn(pExpr, param->pExtInfo);
|
|
||||||
if (pSkipList == NULL) {
|
|
||||||
tSQLListTraverseOnResult(pExpr, param->fp, result);
|
|
||||||
} else {
|
|
||||||
tQueryInfo *pQueryInfo = pExpr->_node.info;
|
|
||||||
|
|
||||||
if (pQueryInfo->colIndex == 0 && pQueryInfo->optr != TSDB_RELATION_LIKE) {
|
|
||||||
SQueryCond cond = {0};
|
|
||||||
/*int32_t ret = */ setQueryCond(pQueryInfo, &cond);
|
|
||||||
tQueryOnSkipList(pSkipList, &cond, pQueryInfo->q.nType, result);
|
|
||||||
} else {
|
|
||||||
/* Brutal force scan the whole skip list to find the appropriate result,
|
|
||||||
* since the filter is not applied to indexed column.
|
|
||||||
*/
|
|
||||||
assert(0);
|
|
||||||
// result->num = tSkipListIterateList(pSkipList, (tSkipListNode ***)&result->pRes, fp, queryColInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (weight == 2 || (weight == 1 && pExpr->_node.optr == TSDB_RELATION_OR)) {
|
||||||
|
SArray* rLeft = taosArrayInit(10, POINTER_BYTES);
|
||||||
|
SArray* rRight = taosArrayInit(10, POINTER_BYTES);
|
||||||
|
|
||||||
|
tExprTreeTraverse(pLeft, pSkipList, rLeft, param);
|
||||||
|
tExprTreeTraverse(pRight, pSkipList, rRight, param);
|
||||||
|
|
||||||
|
if (pExpr->_node.optr == TSDB_RELATION_AND) { // CROSS
|
||||||
|
intersect(rLeft, rRight, result);
|
||||||
|
} else if (pExpr->_node.optr == TSDB_RELATION_OR) { // or
|
||||||
|
merge(rLeft, rRight, result);
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
taosArrayDestroy(rLeft);
|
||||||
|
taosArrayDestroy(rRight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (weight == 1 && pExpr->nSQLBinaryOptr == TSDB_RELATION_AND) is handled here
|
||||||
|
*
|
||||||
|
* first, we filter results based on the skiplist index, which is the initial filter stage,
|
||||||
|
* then, we conduct the secondary filter operation based on the result from the initial filter stage.
|
||||||
|
*/
|
||||||
|
assert(pExpr->_node.optr == TSDB_RELATION_AND);
|
||||||
|
|
||||||
|
tExprNode *pFirst = NULL;
|
||||||
|
tExprNode *pSecond = NULL;
|
||||||
|
if (pLeft->_node.hasPK == 1) {
|
||||||
|
pFirst = pLeft;
|
||||||
|
pSecond = pRight;
|
||||||
|
} else {
|
||||||
|
pFirst = pRight;
|
||||||
|
pSecond = pLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pFirst != pSecond && pFirst != NULL && pSecond != NULL);
|
||||||
|
|
||||||
|
// we filter the result based on the skiplist index in the first place
|
||||||
|
tExprTreeTraverse(pFirst, pSkipList, result, param);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* recursively perform the filter operation based on the initial results,
|
||||||
|
* So, we do not set the skip list index as a parameter
|
||||||
|
*/
|
||||||
|
tExprTreeTraverse(pSecond, NULL, result, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tSQLBinaryExprCalcTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput, void *param, int32_t order,
|
void tSQLBinaryExprCalcTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput, void *param, int32_t order,
|
||||||
char *(*getSourceDataBlock)(void *, char *, int32_t)) {
|
char *(*getSourceDataBlock)(void *, char *, int32_t)) {
|
||||||
if (pExprs == NULL) {
|
if (pExprs == NULL) {
|
||||||
|
@ -1090,12 +1131,6 @@ tExprNode* exprTreeFromBinary(const void* pBuf, size_t size) {
|
||||||
return exprTreeFromBinaryImpl(&rbuf);
|
return exprTreeFromBinaryImpl(&rbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmpStrInArray(const void* a, const void* b) {
|
|
||||||
const char* x = *(const char**)a;
|
|
||||||
const char* y = *(const char**)b;
|
|
||||||
return strcmp(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
||||||
if (!tbnameCond) {
|
if (!tbnameCond) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1132,6 +1167,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
||||||
expr->_node.pRight = right;
|
expr->_node.pRight = right;
|
||||||
|
|
||||||
if (strncmp(tbnameCond, QUERY_COND_REL_PREFIX_LIKE, QUERY_COND_REL_PREFIX_LIKE_LEN) == 0) {
|
if (strncmp(tbnameCond, QUERY_COND_REL_PREFIX_LIKE, QUERY_COND_REL_PREFIX_LIKE_LEN) == 0) {
|
||||||
|
right->nodeType = TSQL_NODE_VALUE;
|
||||||
expr->_node.optr = TSDB_RELATION_LIKE;
|
expr->_node.optr = TSDB_RELATION_LIKE;
|
||||||
tVariant* pVal = calloc(1, sizeof(tVariant));
|
tVariant* pVal = calloc(1, sizeof(tVariant));
|
||||||
if (pVal == NULL) {
|
if (pVal == NULL) {
|
||||||
|
@ -1147,8 +1183,15 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
||||||
memcpy(pVal->pz, tbnameCond + QUERY_COND_REL_PREFIX_LIKE_LEN, len);
|
memcpy(pVal->pz, tbnameCond + QUERY_COND_REL_PREFIX_LIKE_LEN, len);
|
||||||
|
|
||||||
} else if (strncmp(tbnameCond, QUERY_COND_REL_PREFIX_IN, QUERY_COND_REL_PREFIX_IN_LEN) == 0) {
|
} else if (strncmp(tbnameCond, QUERY_COND_REL_PREFIX_IN, QUERY_COND_REL_PREFIX_IN_LEN) == 0) {
|
||||||
|
right->nodeType = TSQL_NODE_VALUE;
|
||||||
expr->_node.optr = TSDB_RELATION_IN;
|
expr->_node.optr = TSDB_RELATION_IN;
|
||||||
right->array = taosArrayInit(2, sizeof(char*));
|
tVariant* pVal = calloc(1, sizeof(tVariant));
|
||||||
|
if (pVal == NULL) {
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
right->pVal = pVal;
|
||||||
|
pVal->nType = TSDB_DATA_TYPE_ARRAY;
|
||||||
|
pVal->arr = taosArrayInit(2, sizeof(char*));
|
||||||
|
|
||||||
const char* cond = tbnameCond + QUERY_COND_REL_PREFIX_IN_LEN;
|
const char* cond = tbnameCond + QUERY_COND_REL_PREFIX_IN_LEN;
|
||||||
for (const char *e = cond; *e != 0; e++) {
|
for (const char *e = cond; *e != 0; e++) {
|
||||||
|
@ -1158,7 +1201,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
||||||
memcpy(p, cond, len);
|
memcpy(p, cond, len);
|
||||||
p[len - 1] = 0;
|
p[len - 1] = 0;
|
||||||
cond += len;
|
cond += len;
|
||||||
taosArrayPush(right->array, &p);
|
taosArrayPush(pVal->arr, &p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1167,10 +1210,10 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
||||||
char* p = malloc( len );
|
char* p = malloc( len );
|
||||||
memcpy(p, cond, len);
|
memcpy(p, cond, len);
|
||||||
p[len - 1] = 0;
|
p[len - 1] = 0;
|
||||||
taosArrayPush(right->array, &p);
|
taosArrayPush(pVal->arr, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
taosArraySort(right->array, cmpStrInArray);
|
taosArraySortString(pVal->arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
|
|
|
@ -130,6 +130,17 @@ void tVariantDestroy(tVariant *pVar) {
|
||||||
tfree(pVar->pz);
|
tfree(pVar->pz);
|
||||||
pVar->nLen = 0;
|
pVar->nLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: this is only for string array
|
||||||
|
if (pVar->nType == TSDB_DATA_TYPE_ARRAY) {
|
||||||
|
size_t num = taosArrayGetSize(pVar->arr);
|
||||||
|
for(size_t i = 0; i < num; i++) {
|
||||||
|
void* p = taosArrayGetP(pVar->arr, i);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
taosArrayDestroy(pVar->arr);
|
||||||
|
pVar->arr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
|
void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
|
||||||
|
@ -145,6 +156,18 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
|
||||||
|
|
||||||
pDst->pz = calloc(1, len);
|
pDst->pz = calloc(1, len);
|
||||||
memcpy(pDst->pz, pSrc->pz, len);
|
memcpy(pDst->pz, pSrc->pz, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is only for string array
|
||||||
|
if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) {
|
||||||
|
size_t num = taosArrayGetSize(pSrc->arr);
|
||||||
|
pDst->arr = taosArrayInit(num, sizeof(char*));
|
||||||
|
for(size_t i = 0; i < num; i++) {
|
||||||
|
char* p = (char*)taosArrayGetP(pSrc->arr, i);
|
||||||
|
char* n = strdup(p);
|
||||||
|
taosArrayPush(pDst->arr, &n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1213,7 +1213,9 @@ void filterPrepare(void* expr, void* param) {
|
||||||
pInfo->compare = getComparFunc(pSchema->type, pCond->nType, pInfo->optr);
|
pInfo->compare = getComparFunc(pSchema->type, pCond->nType, pInfo->optr);
|
||||||
|
|
||||||
tVariantAssign(&pInfo->q, pCond);
|
tVariantAssign(&pInfo->q, pCond);
|
||||||
tVariantTypeSetType(&pInfo->q, pInfo->sch.type);
|
if (pInfo->optr != TSDB_RELATION_IN) {
|
||||||
|
tVariantTypeSetType(&pInfo->q, pInfo->sch.type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) {
|
int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) {
|
||||||
|
|
|
@ -119,13 +119,26 @@ void taosArrayDestroy(SArray* pArray);
|
||||||
*/
|
*/
|
||||||
void taosArraySort(SArray* pArray, int (*compar)(const void*, const void*));
|
void taosArraySort(SArray* pArray, int (*compar)(const void*, const void*));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sort string array
|
||||||
|
* @param pArray
|
||||||
|
*/
|
||||||
|
void taosArraySortString(SArray* pArray);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* search the array
|
* search the array
|
||||||
* @param pArray
|
* @param pArray
|
||||||
* @param compar
|
* @param compar
|
||||||
* @param key
|
* @param key
|
||||||
*/
|
*/
|
||||||
void* taosArraySearch(SArray* pArray, int (*compar)(const void*, const void*), const void* key);
|
void* taosArraySearch(const SArray* pArray, int (*compar)(const void*, const void*), const void* key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search the array
|
||||||
|
* @param pArray
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
char* taosArraySearchString(const SArray* pArray, const char* key);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ void* taosArrayInit(size_t size, size_t elemSize) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pArray->pData = calloc(size, elemSize * size);
|
pArray->pData = calloc(size, elemSize);
|
||||||
if (pArray->pData == NULL) {
|
if (pArray->pData == NULL) {
|
||||||
free(pArray);
|
free(pArray);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -192,10 +192,32 @@ void taosArraySort(SArray* pArray, int (*compar)(const void*, const void*)) {
|
||||||
qsort(pArray->pData, pArray->size, pArray->elemSize, compar);
|
qsort(pArray->pData, pArray->size, pArray->elemSize, compar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* taosArraySearch(SArray* pArray, int (*compar)(const void*, const void*), const void* key) {
|
void* taosArraySearch(const SArray* pArray, int (*compar)(const void*, const void*), const void* key) {
|
||||||
assert(pArray != NULL);
|
assert(pArray != NULL);
|
||||||
assert(compar != NULL);
|
assert(compar != NULL);
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
return bsearch(key, pArray->pData, pArray->size, pArray->elemSize, compar);
|
return bsearch(key, pArray->pData, pArray->size, pArray->elemSize, compar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int taosArrayCompareString(const void* a, const void* b) {
|
||||||
|
const char* x = *(const char**)a;
|
||||||
|
const char* y = *(const char**)b;
|
||||||
|
return strcmp(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void taosArraySortString(SArray* pArray) {
|
||||||
|
assert(pArray != NULL);
|
||||||
|
qsort(pArray->pData, pArray->size, pArray->elemSize, taosArrayCompareString);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* taosArraySearchString(const SArray* pArray, const char* key) {
|
||||||
|
assert(pArray != NULL);
|
||||||
|
assert(key != NULL);
|
||||||
|
|
||||||
|
void* p = bsearch(&key, pArray->pData, pArray->size, pArray->elemSize, taosArrayCompareString);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return *(char**)p;
|
||||||
|
}
|
|
@ -1,42 +1,34 @@
|
||||||
#include "taosdef.h"
|
#include "taosdef.h"
|
||||||
#include "tcompare.h"
|
#include "tcompare.h"
|
||||||
|
#include <tarray.h>
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
|
|
||||||
int32_t compareInt32Val(const void *pLeft, const void *pRight) {
|
int32_t compareInt32Val(const void *pLeft, const void *pRight) {
|
||||||
int32_t ret = GET_INT32_VAL(pLeft) - GET_INT32_VAL(pRight);
|
int32_t left = GET_INT32_VAL(pLeft), right = GET_INT32_VAL(pRight);
|
||||||
if (ret == 0) {
|
if (left > right) return 1;
|
||||||
return 0;
|
if (left < right) return -1;
|
||||||
} else {
|
return 0;
|
||||||
return ret > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareInt64Val(const void *pLeft, const void *pRight) {
|
int32_t compareInt64Val(const void *pLeft, const void *pRight) {
|
||||||
int64_t ret = GET_INT64_VAL(pLeft) - GET_INT64_VAL(pRight);
|
int64_t left = GET_INT64_VAL(pLeft), right = GET_INT64_VAL(pRight);
|
||||||
if (ret == 0) {
|
if (left > right) return 1;
|
||||||
return 0;
|
if (left < right) return -1;
|
||||||
} else {
|
return 0;
|
||||||
return ret > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareInt16Val(const void *pLeft, const void *pRight) {
|
int32_t compareInt16Val(const void *pLeft, const void *pRight) {
|
||||||
int32_t ret = GET_INT16_VAL(pLeft) - GET_INT16_VAL(pRight);
|
int16_t left = GET_INT16_VAL(pLeft), right = GET_INT16_VAL(pRight);
|
||||||
if (ret == 0) {
|
if (left > right) return 1;
|
||||||
return 0;
|
if (left < right) return -1;
|
||||||
} else {
|
return 0;
|
||||||
return ret > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareInt8Val(const void *pLeft, const void *pRight) {
|
int32_t compareInt8Val(const void *pLeft, const void *pRight) {
|
||||||
int32_t ret = GET_INT8_VAL(pLeft) - GET_INT8_VAL(pRight);
|
int8_t left = GET_INT8_VAL(pLeft), right = GET_INT8_VAL(pRight);
|
||||||
if (ret == 0) {
|
if (left > right) return 1;
|
||||||
return 0;
|
if (left < right) return -1;
|
||||||
} else {
|
return 0;
|
||||||
return ret > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareIntDoubleVal(const void *pLeft, const void *pRight) {
|
int32_t compareIntDoubleVal(const void *pLeft, const void *pRight) {
|
||||||
|
@ -69,12 +61,7 @@ int32_t compareDoubleVal(const void *pLeft, const void *pRight) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareStrVal(const void *pLeft, const void *pRight) {
|
int32_t compareStrVal(const void *pLeft, const void *pRight) {
|
||||||
int32_t ret = strcmp(pLeft, pRight);
|
return (int32_t)strcmp(pLeft, pRight);
|
||||||
if (ret == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return ret > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareWStrVal(const void *pLeft, const void *pRight) {
|
int32_t compareWStrVal(const void *pLeft, const void *pRight) {
|
||||||
|
@ -228,6 +215,11 @@ static UNUSED_FUNC int32_t compareStrPatternComp(const void* pLeft, const void*
|
||||||
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t compareStrInList(const void* pLeft, const void* pRight) {
|
||||||
|
const SArray* arr = (const SArray*)pRight;
|
||||||
|
return taosArraySearchString(arr, &pLeft) == NULL ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
static UNUSED_FUNC int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) {
|
static UNUSED_FUNC int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) {
|
||||||
SPatternCompareInfo pInfo = {'%', '_'};
|
SPatternCompareInfo pInfo = {'%', '_'};
|
||||||
|
|
||||||
|
@ -250,7 +242,6 @@ __compar_fn_t getComparFunc(int32_t type, int32_t filterDataType, int32_t optr)
|
||||||
case TSDB_DATA_TYPE_BIGINT:
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||||
// assert(type == filterDataType);
|
// assert(type == filterDataType);
|
||||||
|
|
||||||
if (filterDataType == TSDB_DATA_TYPE_BIGINT || filterDataType == TSDB_DATA_TYPE_TIMESTAMP) {
|
if (filterDataType == TSDB_DATA_TYPE_BIGINT || filterDataType == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||||
comparFn = compareInt64Val;
|
comparFn = compareInt64Val;
|
||||||
} else if (filterDataType >= TSDB_DATA_TYPE_FLOAT && filterDataType <= TSDB_DATA_TYPE_DOUBLE) {
|
} else if (filterDataType >= TSDB_DATA_TYPE_FLOAT && filterDataType <= TSDB_DATA_TYPE_DOUBLE) {
|
||||||
|
@ -259,6 +250,7 @@ __compar_fn_t getComparFunc(int32_t type, int32_t filterDataType, int32_t optr)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_BOOL: {
|
case TSDB_DATA_TYPE_BOOL: {
|
||||||
if (filterDataType >= TSDB_DATA_TYPE_BOOL && filterDataType <= TSDB_DATA_TYPE_BIGINT) {
|
if (filterDataType >= TSDB_DATA_TYPE_BOOL && filterDataType <= TSDB_DATA_TYPE_BIGINT) {
|
||||||
comparFn = compareInt32Val;
|
comparFn = compareInt32Val;
|
||||||
|
@ -267,6 +259,7 @@ __compar_fn_t getComparFunc(int32_t type, int32_t filterDataType, int32_t optr)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_FLOAT:
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
case TSDB_DATA_TYPE_DOUBLE: {
|
case TSDB_DATA_TYPE_DOUBLE: {
|
||||||
if (filterDataType >= TSDB_DATA_TYPE_BOOL && filterDataType <= TSDB_DATA_TYPE_BIGINT) {
|
if (filterDataType >= TSDB_DATA_TYPE_BOOL && filterDataType <= TSDB_DATA_TYPE_BIGINT) {
|
||||||
|
@ -276,12 +269,18 @@ __compar_fn_t getComparFunc(int32_t type, int32_t filterDataType, int32_t optr)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_BINARY: {
|
case TSDB_DATA_TYPE_BINARY: {
|
||||||
assert(filterDataType == TSDB_DATA_TYPE_BINARY);
|
|
||||||
|
|
||||||
if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */
|
if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */
|
||||||
|
assert(filterDataType == TSDB_DATA_TYPE_BINARY);
|
||||||
comparFn = compareStrPatternComp;
|
comparFn = compareStrPatternComp;
|
||||||
|
|
||||||
|
} else if (optr == TSDB_RELATION_IN) {
|
||||||
|
assert(filterDataType == TSDB_DATA_TYPE_ARRAY);
|
||||||
|
comparFn = compareStrInList;
|
||||||
|
|
||||||
} else { /* normal relational comparFn */
|
} else { /* normal relational comparFn */
|
||||||
|
assert(filterDataType == TSDB_DATA_TYPE_BINARY);
|
||||||
comparFn = compareStrVal;
|
comparFn = compareStrVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue