commit
85d3a7a207
|
@ -63,6 +63,9 @@ static SExprInfo* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int3
|
|||
static int32_t setShowInfo(SSqlObj* pSql, SSqlInfo* pInfo);
|
||||
static char* getAccountId(SSqlObj* pSql);
|
||||
|
||||
static bool serializeExprListToVariant(SArray* pList, tVariant **dest, int16_t colType);
|
||||
static int32_t validateParamOfRelationIn(tVariant *pVar, int32_t colType);
|
||||
|
||||
static bool has(SArray* pFieldList, int32_t startIdx, const char* name);
|
||||
static char* cloneCurrentDBName(SSqlObj* pSql);
|
||||
static int32_t getDelimiterIndex(SStrToken* pTableName);
|
||||
|
@ -138,10 +141,93 @@ static bool isTimeWindowQuery(SQueryInfo* pQueryInfo) {
|
|||
return pQueryInfo->interval.interval > 0 || pQueryInfo->sessionWindow.gap > 0;
|
||||
}
|
||||
|
||||
|
||||
int16_t getNewResColId(SSqlCmd* pCmd) {
|
||||
return pCmd->resColumnId--;
|
||||
}
|
||||
|
||||
// serialize expr in exprlist to binary
|
||||
// formate "type | size | value"
|
||||
bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType) {
|
||||
bool ret = false;
|
||||
if (!pList || pList->size <= 0) {
|
||||
return ret;
|
||||
}
|
||||
if (colType == TSDB_DATA_TYPE_DOUBLE || colType == TSDB_DATA_TYPE_FLOAT) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
tSqlExprItem* item = (tSqlExprItem *)taosArrayGet(pList, 0);
|
||||
int32_t firstTokenType = item->pNode->token.type;
|
||||
int32_t type = firstTokenType;
|
||||
|
||||
//nchar to binary and
|
||||
toTSDBType(type);
|
||||
if (type != colType && (type != TSDB_DATA_TYPE_BINARY || colType != TSDB_DATA_TYPE_NCHAR)) {
|
||||
return false;
|
||||
}
|
||||
type = colType;
|
||||
|
||||
SBufferWriter bw = tbufInitWriter( NULL, false );
|
||||
tbufEnsureCapacity(&bw, 512);
|
||||
|
||||
int32_t size = (int32_t)(pList->size);
|
||||
tbufWriteUint32(&bw, type);
|
||||
tbufWriteInt32(&bw, size);
|
||||
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
tSqlExpr* pSub = ((tSqlExprItem*)(taosArrayGet(pList, i)))->pNode;
|
||||
|
||||
// check all the token type in expr list same or not
|
||||
if (firstTokenType != pSub->token.type) {
|
||||
break;
|
||||
}
|
||||
|
||||
toTSDBType(pSub->token.type);
|
||||
|
||||
tVariant var;
|
||||
tVariantCreate(&var, &pSub->token);
|
||||
if (type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_SMALLINT
|
||||
|| type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_INT) {
|
||||
tbufWriteInt64(&bw, var.i64);
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
|
||||
tbufWriteDouble(&bw, var.dKey);
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY){
|
||||
tbufWriteBinary(&bw, var.pz, var.nLen);
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR) {
|
||||
char *buf = (char *)calloc(1, (var.nLen + 1)*TSDB_NCHAR_SIZE);
|
||||
if (tVariantDump(&var, buf, type, false) != TSDB_CODE_SUCCESS) {
|
||||
free(buf);
|
||||
tVariantDestroy(&var);
|
||||
break;
|
||||
}
|
||||
tbufWriteBinary(&bw, buf, twcslen((wchar_t *)buf) * TSDB_NCHAR_SIZE);
|
||||
free(buf);
|
||||
}
|
||||
tVariantDestroy(&var);
|
||||
|
||||
if (i == size - 1) { ret = true;}
|
||||
}
|
||||
|
||||
if (ret == true) {
|
||||
if ((*dst = calloc(1, sizeof(tVariant))) != NULL) {
|
||||
tVariantCreateFromBinary(*dst, tbufGetData(&bw, false), tbufTell(&bw), TSDB_DATA_TYPE_BINARY);
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
tbufCloseWriter(&bw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t validateParamOfRelationIn(tVariant *pVar, int32_t colType) {
|
||||
if (pVar->nType != TSDB_DATA_TYPE_BINARY) {
|
||||
return -1;
|
||||
}
|
||||
SBufferReader br = tbufInitReader(pVar->pz, pVar->nLen, false);
|
||||
return colType == TSDB_DATA_TYPE_NCHAR ? 0 : (tbufReadUint32(&br) == colType ? 0: -1);
|
||||
}
|
||||
|
||||
static uint8_t convertOptr(SStrToken *pToken) {
|
||||
switch (pToken->type) {
|
||||
case TK_LT:
|
||||
|
@ -162,6 +248,7 @@ static uint8_t convertOptr(SStrToken *pToken) {
|
|||
return TSDB_RELATION_EQUAL;
|
||||
case TK_PLUS:
|
||||
return TSDB_BINARY_OP_ADD;
|
||||
|
||||
case TK_MINUS:
|
||||
return TSDB_BINARY_OP_SUBTRACT;
|
||||
case TK_STAR:
|
||||
|
@ -177,6 +264,8 @@ static uint8_t convertOptr(SStrToken *pToken) {
|
|||
return TSDB_RELATION_ISNULL;
|
||||
case TK_NOTNULL:
|
||||
return TSDB_RELATION_NOTNULL;
|
||||
case TK_IN:
|
||||
return TSDB_RELATION_IN;
|
||||
default: { return 0; }
|
||||
}
|
||||
}
|
||||
|
@ -3229,6 +3318,25 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
|
|||
retVal = tVariantDump(&pRight->value, (char*)&pColumnFilter->upperBndd, colType, false);
|
||||
|
||||
// TK_GT,TK_GE,TK_EQ,TK_NE are based on the pColumn->lowerBndd
|
||||
} else if (pExpr->tokenId == TK_IN) {
|
||||
tVariant *pVal;
|
||||
if (pRight->tokenId != TK_SET || !serializeExprListToVariant(pRight->pParam, &pVal, colType) || colType == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
if (validateParamOfRelationIn(pVal, colType) != TSDB_CODE_SUCCESS) {
|
||||
tVariantDestroy(pVal);
|
||||
free(pVal);
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
pColumnFilter->pz = (int64_t)calloc(1, pVal->nLen + 1);
|
||||
pColumnFilter->len = pVal->nLen;
|
||||
pColumnFilter->filterstr = 1;
|
||||
memcpy((char *)(pColumnFilter->pz), (char *)(pVal->pz), pVal->nLen);
|
||||
//retVal = tVariantDump(pVal, (char *)(pColumnFilter->pz), TSDB_DATA_TYPE_BINARY, false);
|
||||
|
||||
tVariantDestroy(pVal);
|
||||
free(pVal);
|
||||
|
||||
} else if (colType == TSDB_DATA_TYPE_BINARY) {
|
||||
pColumnFilter->pz = (int64_t)calloc(1, bufLen * TSDB_NCHAR_SIZE);
|
||||
pColumnFilter->len = pRight->value.nLen;
|
||||
|
@ -3277,6 +3385,9 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
|
|||
case TK_NOTNULL:
|
||||
pColumnFilter->lowerRelOptr = TSDB_RELATION_NOTNULL;
|
||||
break;
|
||||
case TK_IN:
|
||||
pColumnFilter->lowerRelOptr = TSDB_RELATION_IN;
|
||||
break;
|
||||
default:
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
|
@ -3392,7 +3503,7 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC
|
|||
&& pExpr->tokenId != TK_ISNULL
|
||||
&& pExpr->tokenId != TK_NOTNULL
|
||||
&& pExpr->tokenId != TK_LIKE
|
||||
) {
|
||||
&& pExpr->tokenId != TK_IN) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
} else {
|
||||
|
@ -3402,7 +3513,7 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC
|
|||
|
||||
if (pSchema->type == TSDB_DATA_TYPE_BOOL) {
|
||||
int32_t t = pExpr->tokenId;
|
||||
if (t != TK_EQ && t != TK_NE && t != TK_NOTNULL && t != TK_ISNULL) {
|
||||
if (t != TK_EQ && t != TK_NE && t != TK_NOTNULL && t != TK_ISNULL && t != TK_IN) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
}
|
||||
|
@ -4444,8 +4555,12 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) {
|
|||
free(tmp);
|
||||
} else {
|
||||
double tmp;
|
||||
if (p->_node.optr == TSDB_RELATION_IN) {
|
||||
retVal = validateParamOfRelationIn(vVariant, schemaType);
|
||||
} else {
|
||||
retVal = tVariantDump(vVariant, (char*)&tmp, schemaType, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (retVal != TSDB_CODE_SUCCESS) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
|
@ -7953,6 +8068,24 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS
|
|||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else if (pSqlExpr->tokenId == TK_SET) {
|
||||
int32_t type = -1;
|
||||
STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta;
|
||||
if (pCols != NULL) {
|
||||
SColIndex* idx = taosArrayGet(pCols, 0);
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, idx->colIndex);
|
||||
if (pSchema != NULL) {
|
||||
type = pSchema->type;
|
||||
}
|
||||
}
|
||||
|
||||
tVariant *pVal;
|
||||
if (serializeExprListToVariant(pSqlExpr->pParam, &pVal, type) == false) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "not support filter expression");
|
||||
}
|
||||
*pExpr = calloc(1, sizeof(tExprNode));
|
||||
(*pExpr)->nodeType = TSQL_NODE_VALUE;
|
||||
(*pExpr)->pVal = pVal;
|
||||
} else {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "not support filter expression");
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ bool exprTreeApplyFilter(tExprNode *pExpr, const void *pItem, SExprTraverseSupp
|
|||
void arithmeticTreeTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput, void *param, int32_t order,
|
||||
char *(*cb)(void *, const char*, int32_t));
|
||||
|
||||
void buildFilterSetFromBinary(void **q, const char *buf, int32_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -466,6 +466,32 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
|||
return expr;
|
||||
}
|
||||
|
||||
void buildFilterSetFromBinary(void **q, const char *buf, int32_t len) {
|
||||
SBufferReader br = tbufInitReader(buf, len, false);
|
||||
uint32_t type = tbufReadUint32(&br);
|
||||
SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(type), true, false);
|
||||
int dummy = -1;
|
||||
int32_t sz = tbufReadInt32(&br);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
if (type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_SMALLINT || type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_INT) {
|
||||
int64_t val = tbufReadInt64(&br);
|
||||
taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy));
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
|
||||
double val = tbufReadDouble(&br);
|
||||
taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy));
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
size_t t = 0;
|
||||
const char *val = tbufReadBinary(&br, &t);
|
||||
taosHashPut(pObj, (char *)val, t, &dummy, sizeof(dummy));
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR) {
|
||||
size_t t = 0;
|
||||
const char *val = tbufReadBinary(&br, &t);
|
||||
taosHashPut(pObj, (char *)val, t, &dummy, sizeof(dummy));
|
||||
}
|
||||
}
|
||||
*q = (void *)pObj;
|
||||
}
|
||||
|
||||
tExprNode* exprdup(tExprNode* pNode) {
|
||||
if (pNode == NULL) {
|
||||
return NULL;
|
||||
|
|
|
@ -113,6 +113,7 @@ typedef struct SColumnFilterElem {
|
|||
int16_t bytes; // column length
|
||||
__filter_func_t fp;
|
||||
SColumnFilterInfo filterInfo;
|
||||
void *q;
|
||||
} SColumnFilterElem;
|
||||
|
||||
typedef struct SSingleColumnFilterInfo {
|
||||
|
|
|
@ -6942,6 +6942,10 @@ int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfF
|
|||
}
|
||||
|
||||
pSingleColFilter->bytes = pCols[i].bytes;
|
||||
|
||||
if (lower == TSDB_RELATION_IN) {
|
||||
buildFilterSetFromBinary(&pSingleColFilter->q, (char *)(pSingleColFilter->filterInfo.pz), (int32_t)(pSingleColFilter->filterInfo.len));
|
||||
}
|
||||
}
|
||||
|
||||
j++;
|
||||
|
@ -6954,6 +6958,9 @@ int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfF
|
|||
void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) {
|
||||
for (int32_t i = 0; i < numOfFilterCols; ++i) {
|
||||
if (pFilterInfo[i].numOfFilters > 0) {
|
||||
if (pFilterInfo[i].pFilters->filterInfo.lowerRelOptr == TSDB_RELATION_IN) {
|
||||
taosHashCleanup((SHashObj *)(pFilterInfo[i].pFilters->q));
|
||||
}
|
||||
tfree(pFilterInfo[i].pFilters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,6 +253,27 @@ bool isNullOperator(SColumnFilterElem *pFilter, const char* minval, const char*
|
|||
bool notNullOperator(SColumnFilterElem *pFilter, const char* minval, const char* maxval, int16_t type) {
|
||||
return true;
|
||||
}
|
||||
bool inOperator(SColumnFilterElem *pFilter, const char* minval, const char* maxval, int16_t type) {
|
||||
if (type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_SMALLINT || type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_INT) {
|
||||
int64_t minv = -1, maxv = -1;
|
||||
GET_TYPED_DATA(minv, int64_t, type, minval);
|
||||
GET_TYPED_DATA(maxv, int64_t, type, maxval);
|
||||
if (minv == maxv) {
|
||||
return NULL != taosHashGet((SHashObj *)pFilter->q, (char *)&minv, sizeof(minv));
|
||||
}
|
||||
return true;
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double v;
|
||||
GET_TYPED_DATA(v, double, type, minval);
|
||||
return NULL != taosHashGet((SHashObj *)pFilter->q, (char *)&v, sizeof(v));
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
return NULL != taosHashGet((SHashObj *)pFilter->q, varDataVal(minval), varDataLen(minval));
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR){
|
||||
return NULL != taosHashGet((SHashObj *)pFilter->q, varDataVal(minval), varDataLen(minval));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool rangeFilter_ii(SColumnFilterElem *pFilter, const char *minval, const char *maxval, int16_t type) {
|
||||
|
@ -389,6 +410,7 @@ bool (*filterOperators[])(SColumnFilterElem *pFilter, const char* minval, const
|
|||
likeOperator,
|
||||
isNullOperator,
|
||||
notNullOperator,
|
||||
inOperator,
|
||||
};
|
||||
|
||||
bool (*rangeFilterOperators[])(SColumnFilterElem *pFilter, const char* minval, const char* maxval, int16_t type) = {
|
||||
|
@ -397,6 +419,7 @@ bool (*rangeFilterOperators[])(SColumnFilterElem *pFilter, const char* minval, c
|
|||
rangeFilter_ie,
|
||||
rangeFilter_ei,
|
||||
rangeFilter_ii,
|
||||
|
||||
};
|
||||
|
||||
__filter_func_t getFilterOperator(int32_t lowerOptr, int32_t upperOptr) {
|
||||
|
|
|
@ -2397,6 +2397,8 @@ static void destroyHelper(void* param) {
|
|||
tQueryInfo* pInfo = (tQueryInfo*)param;
|
||||
if (pInfo->optr != TSDB_RELATION_IN) {
|
||||
tfree(pInfo->q);
|
||||
} else {
|
||||
taosHashCleanup((SHashObj *)(pInfo->q));
|
||||
}
|
||||
|
||||
free(param);
|
||||
|
@ -3155,11 +3157,23 @@ void filterPrepare(void* expr, void* param) {
|
|||
|
||||
pInfo->sch = *pSchema;
|
||||
pInfo->optr = pExpr->_node.optr;
|
||||
pInfo->compare = getComparFunc(pSchema->type, pInfo->optr);
|
||||
pInfo->compare = getComparFunc(pInfo->sch.type, pInfo->optr);
|
||||
pInfo->indexed = pTSSchema->columns->colId == pInfo->sch.colId;
|
||||
|
||||
if (pInfo->optr == TSDB_RELATION_IN) {
|
||||
pInfo->q = (char*) pCond->arr;
|
||||
int dummy = -1;
|
||||
SHashObj *pObj = NULL;
|
||||
if (pInfo->sch.colId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
pObj = taosHashInit(256, taosGetDefaultHashFunction(pInfo->sch.type), true, false);
|
||||
SArray *arr = (SArray *)(pCond->arr);
|
||||
for (size_t i = 0; i < taosArrayGetSize(arr); i++) {
|
||||
char* p = taosArrayGetP(arr, i);
|
||||
taosHashPut(pObj, varDataVal(p),varDataLen(p), &dummy, sizeof(dummy));
|
||||
}
|
||||
} else {
|
||||
buildFilterSetFromBinary((void **)&pObj, pCond->pz, pCond->nLen);
|
||||
}
|
||||
pInfo->q = (char *)pObj;
|
||||
} else if (pCond != NULL) {
|
||||
uint32_t size = pCond->nLen * TSDB_NCHAR_SIZE;
|
||||
if (size < (uint32_t)pSchema->bytes) {
|
||||
|
@ -3330,6 +3344,20 @@ static bool tableFilterFp(const void* pNode, void* param) {
|
|||
} else if (pInfo->optr == TSDB_RELATION_NOTNULL) {
|
||||
return (val != NULL) && (!isNull(val, pInfo->sch.type));
|
||||
}
|
||||
} else if (pInfo->optr == TSDB_RELATION_IN) {
|
||||
int type = pInfo->sch.type;
|
||||
if (type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_SMALLINT || type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_INT) {
|
||||
int64_t v;
|
||||
GET_TYPED_DATA(v, int64_t, pInfo->sch.type, val);
|
||||
return NULL != taosHashGet((SHashObj *)pInfo->q, (char *)&v, sizeof(v));
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double v;
|
||||
GET_TYPED_DATA(v, double, pInfo->sch.type, val);
|
||||
return NULL != taosHashGet((SHashObj *)pInfo->q, (char *)&v, sizeof(v));
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR){
|
||||
return NULL != taosHashGet((SHashObj *)pInfo->q, varDataVal(val), varDataLen(val));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int32_t ret = 0;
|
||||
|
@ -3679,7 +3707,11 @@ static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
|
|||
pCond->end = calloc(1, sizeof(SEndPoint));
|
||||
pCond->end->optr = queryColInfo->optr;
|
||||
pCond->end->v = queryColInfo->q;
|
||||
} else if (optr == TSDB_RELATION_IN || optr == TSDB_RELATION_LIKE) {
|
||||
} else if (optr == TSDB_RELATION_IN) {
|
||||
pCond->start = calloc(1, sizeof(SEndPoint));
|
||||
pCond->start->optr = queryColInfo->optr;
|
||||
pCond->start->v = queryColInfo->q;
|
||||
} else if (optr == TSDB_RELATION_LIKE) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
@ -3764,6 +3796,19 @@ static void queryIndexedColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SAr
|
|||
taosArrayPush(result, &info);
|
||||
}
|
||||
|
||||
} else if (optr == TSDB_RELATION_IN) {
|
||||
while(tSkipListIterNext(iter)) {
|
||||
SSkipListNode* pNode = tSkipListIterGet(iter);
|
||||
|
||||
int32_t ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v);
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
STableKeyInfo info = {.pTable = (void*)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
|
||||
taosArrayPush(result, &info);
|
||||
}
|
||||
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
@ -3857,7 +3902,7 @@ void getTableListfromSkipList(tExprNode *pExpr, SSkipList *pSkipList, SArray *re
|
|||
param->setupInfoFn(pExpr, param->pExtInfo);
|
||||
|
||||
tQueryInfo *pQueryInfo = pExpr->_node.info;
|
||||
if (pQueryInfo->indexed && pQueryInfo->optr != TSDB_RELATION_LIKE) {
|
||||
if (pQueryInfo->indexed && (pQueryInfo->optr != TSDB_RELATION_LIKE && pQueryInfo->optr != TSDB_RELATION_IN)) {
|
||||
queryIndexedColumn(pSkipList, pQueryInfo, result);
|
||||
} else {
|
||||
queryIndexlessColumn(pSkipList, pQueryInfo, result, param->nodeFilterFn);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "ttype.h"
|
||||
#include "tcompare.h"
|
||||
#include "tarray.h"
|
||||
#include "hash.h"
|
||||
|
||||
int32_t compareInt32Val(const void *pLeft, const void *pRight) {
|
||||
int32_t left = GET_INT32_VAL(pLeft), right = GET_INT32_VAL(pRight);
|
||||
|
@ -291,9 +292,12 @@ int32_t taosArrayCompareString(const void* a, const void* b) {
|
|||
return compareLenPrefixedStr(x, y);
|
||||
}
|
||||
|
||||
static int32_t compareFindStrInArray(const void* pLeft, const void* pRight) {
|
||||
const SArray* arr = (const SArray*) pRight;
|
||||
return taosArraySearchString(arr, pLeft, taosArrayCompareString, TD_EQ) == NULL ? 0 : 1;
|
||||
//static int32_t compareFindStrInArray(const void* pLeft, const void* pRight) {
|
||||
// const SArray* arr = (const SArray*) pRight;
|
||||
// return taosArraySearchString(arr, pLeft, taosArrayCompareString, TD_EQ) == NULL ? 0 : 1;
|
||||
//}
|
||||
static int32_t compareFindItemInSet(const void *pLeft, const void* pRight) {
|
||||
return NULL != taosHashGet((SHashObj *)pRight, varDataVal(pLeft), varDataLen(pLeft)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) {
|
||||
|
@ -325,7 +329,7 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
|||
if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */
|
||||
comparFn = compareStrPatternComp;
|
||||
} else if (optr == TSDB_RELATION_IN) {
|
||||
comparFn = compareFindStrInArray;
|
||||
comparFn = compareFindItemInSet;
|
||||
} else { /* normal relational comparFn */
|
||||
comparFn = compareLenPrefixedStr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
###################################################################
|
||||
# Copyright (c) 2016 by TAOS Technologies, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is proprietary and confidential to TAOS Technologies.
|
||||
# No part of this file may be reproduced, stored, transmitted,
|
||||
# disclosed or used in any form or by any means other than as
|
||||
# expressly provided by the written permission from Jianhui Tao
|
||||
#
|
||||
###################################################################
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import taos
|
||||
from util.log import tdLog
|
||||
from util.cases import tdCases
|
||||
from util.sql import tdSql
|
||||
from util.dnodes import tdDnodes
|
||||
|
||||
class TDTestCase:
|
||||
def init(self, conn, logSql):
|
||||
tdLog.debug("start to execute %s" % __file__)
|
||||
tdSql.init(conn.cursor(), logSql)
|
||||
|
||||
self.ts = 1538548685000
|
||||
|
||||
def run(self):
|
||||
tdSql.prepare()
|
||||
|
||||
print("==============step1")
|
||||
tdSql.execute(
|
||||
"create table if not exists st (ts timestamp, tagtype int) tags(dev nchar(50))")
|
||||
tdSql.execute(
|
||||
'CREATE TABLE if not exists dev_001 using st tags("dev_01")')
|
||||
tdSql.execute(
|
||||
'CREATE TABLE if not exists dev_002 using st tags("dev_02")')
|
||||
|
||||
print("==============step2")
|
||||
tdSql.error("select * from db.st where ts in ('2020-05-13 10:00:00.000')")
|
||||
|
||||
tdSql.execute(
|
||||
"""INSERT INTO dev_001(ts, tagtype) VALUES('2020-05-13 10:00:00.000', 1),
|
||||
('2020-05-13 10:00:00.001', 1)
|
||||
dev_002 VALUES('2020-05-13 10:00:00.001', 1)""")
|
||||
|
||||
# TAG nchar
|
||||
tdSql.query('select count(ts) from db.st where dev in ("dev_01")')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 2)
|
||||
|
||||
tdSql.query('select count(ts) from db.st where dev in ("dev_01", "dev_01")')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 2)
|
||||
|
||||
tdSql.query('select count(ts) from db.st where dev in ("dev_01", "dev_01", "dev_02")')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
|
||||
|
||||
# colume int
|
||||
tdSql.query("select count(ts) from db.st where tagtype in (1)")
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
|
||||
tdSql.query("select count(ts) from db.st where tagtype in (1, 2)")
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.execute(
|
||||
"""INSERT INTO dev_001(ts, tagtype) VALUES('2020-05-13 10:00:01.000', 2),
|
||||
('2020-05-13 10:00:02.001', 2)
|
||||
dev_002 VALUES('2020-05-13 10:00:03.001', 2)""")
|
||||
|
||||
tdSql.query("select count(ts) from db.st where tagtype in (1, 2)")
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 6)
|
||||
|
||||
tdSql.execute("create table tb(ts timestamp, c1 int, c2 binary(10), c3 nchar(10), c4 float, c5 bool)")
|
||||
for i in range(10):
|
||||
tdSql.execute("insert into tb values(%d, %d, 'binary%d', 'nchar%d', %f, %d)" % (self.ts + i, i, i, i, i + 0.1, i % 2))
|
||||
|
||||
#binary
|
||||
tdSql.query('select count(ts) from db.tb where c2 in ("binary1")')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 1)
|
||||
|
||||
tdSql.query('select count(ts) from db.tb where c2 in ("binary1", "binary2", "binary1")')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 2)
|
||||
|
||||
#bool
|
||||
#tdSql.query('select count(ts) from db.tb where c5 in (true)')
|
||||
#tdSql.checkRows(1)
|
||||
#tdSql.checkData(0, 0, 5)
|
||||
|
||||
#float
|
||||
#tdSql.query('select count(ts) from db.tb where c4 in (0.1)')
|
||||
#tdSql.checkRows(1)
|
||||
#tdSql.checkData(0, 0, 1)
|
||||
|
||||
#nchar
|
||||
tdSql.query('select count(ts) from db.tb where c3 in ("nchar0")')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 1)
|
||||
|
||||
|
||||
#tdSql.query("select tbname, dev from dev_001")
|
||||
#tdSql.checkRows(1)
|
||||
#tdSql.checkData(0, 0, 'dev_001')
|
||||
#tdSql.checkData(0, 1, 'dev_01')
|
||||
|
||||
#tdSql.query("select tbname, dev, tagtype from dev_001")
|
||||
#tdSql.checkRows(2)
|
||||
|
||||
### test case for https://jira.taosdata.com:18080/browse/TD-1930
|
||||
#tdSql.execute("create table tb(ts timestamp, c1 int, c2 binary(10), c3 nchar(10), c4 float, c5 bool)")
|
||||
#for i in range(10):
|
||||
# tdSql.execute("insert into tb values(%d, %d, 'binary%d', 'nchar%d', %f, %d)" % (self.ts + i, i, i, i, i + 0.1, i % 2))
|
||||
#
|
||||
#tdSql.error("select * from tb where c2 = binary2")
|
||||
#tdSql.error("select * from tb where c3 = nchar2")
|
||||
|
||||
#tdSql.query("select * from tb where c2 = 'binary2' ")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
#tdSql.query("select * from tb where c3 = 'nchar2' ")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
#tdSql.query("select * from tb where c1 = '2' ")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
#tdSql.query("select * from tb where c1 = 2 ")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
#tdSql.query("select * from tb where c4 = '0.1' ")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
#tdSql.query("select * from tb where c4 = 0.1 ")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
#tdSql.query("select * from tb where c5 = true ")
|
||||
#tdSql.checkRows(5)
|
||||
|
||||
#tdSql.query("select * from tb where c5 = 'true' ")
|
||||
#tdSql.checkRows(5)
|
||||
|
||||
## For jira: https://jira.taosdata.com:18080/browse/TD-2850
|
||||
#tdSql.execute("create database 'Test' ")
|
||||
#tdSql.execute("use 'Test' ")
|
||||
#tdSql.execute("create table 'TB'(ts timestamp, 'Col1' int) tags('Tag1' int)")
|
||||
#tdSql.execute("insert into 'Tb0' using tb tags(1) values(now, 1)")
|
||||
#tdSql.query("select * from tb")
|
||||
#tdSql.checkRows(1)
|
||||
|
||||
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success("%s successfully executed" % __file__)
|
||||
|
||||
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
|
@ -151,18 +151,12 @@ sql_error select last(*) from wh_mt1 where c5 in ('1')
|
|||
sql_error select last(*) from wh_mt1_tb1 where c5 in ('1')
|
||||
sql_error select last(*) from wh_mt1 where c6 in ('1')
|
||||
sql_error select last(*) from wh_mt1_tb1 where c6 in ('1')
|
||||
sql_error select last(*) from wh_mt1 where c7 in ('binary')
|
||||
sql_error select last(*) from wh_mt1_tb1 where c7 in ('binary')
|
||||
sql_error select last(*) from wh_mt1 where c8 in ('nchar')
|
||||
sql_error select last(*) from wh_mt1_tb1 where c9 in (true, false)
|
||||
#sql_error select last(*) from wh_mt1 where c7 in ('binary')
|
||||
#sql_error select last(*) from wh_mt1_tb1 where c7 in ('binary')
|
||||
#sql_error select last(*) from wh_mt1 where c8 in ('nchar')
|
||||
#sql_error select last(*) from wh_mt1_tb1 where c9 in (true, false)
|
||||
sql_error select last(*) from wh_mt1 where c10 in ('2019-01-01 00:00:00.000')
|
||||
sql_error select last(*) from wh_mt1_tb1 where c10 in ('2019-01-01 00:00:00.000')
|
||||
sql_error select last(*) from wh_mt1 where t1 in ('binary')
|
||||
sql_error select last(*) from wh_mt1 where t2 in (1)
|
||||
sql_error select last(*) from wh_mt1 where t3 in (1)
|
||||
sql_error select last(*) from wh_mt1 where t4 in (1)
|
||||
sql_error select last(*) from wh_mt1 where t5 in (1)
|
||||
sql_error select last(*) from wh_mt1 where t6 in (1)
|
||||
sql select last(*) from wh_mt1 where c1 = 1
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
|
|
Loading…
Reference in New Issue