[TD-1978]
This commit is contained in:
parent
276b7a6dbb
commit
2b9a3b1e1b
|
@ -69,7 +69,10 @@ static void getColumnName(tSQLExprItem* pItem, char* resultFieldName, int32_t na
|
||||||
static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExprItem* pItem, bool finalResult);
|
static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExprItem* pItem, bool finalResult);
|
||||||
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
|
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
|
||||||
int8_t type, char* fieldName, SSqlExpr* pSqlExpr);
|
int8_t type, char* fieldName, SSqlExpr* pSqlExpr);
|
||||||
static int32_t changeFunctionID(int32_t optr, int16_t* functionId);
|
|
||||||
|
static int32_t convertFunctionId(int32_t optr, int16_t* functionId);
|
||||||
|
static uint8_t convertOptr(SStrToken *pToken);
|
||||||
|
|
||||||
static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery);
|
static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery);
|
||||||
|
|
||||||
static bool validateIpAddress(const char* ip, size_t size);
|
static bool validateIpAddress(const char* ip, size_t size);
|
||||||
|
@ -123,6 +126,45 @@ static int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo);
|
||||||
static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index);
|
static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index);
|
||||||
static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid);
|
static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid);
|
||||||
|
|
||||||
|
static uint8_t convertOptr(SStrToken *pToken) {
|
||||||
|
switch (pToken->type) {
|
||||||
|
case TK_LT:
|
||||||
|
return TSDB_RELATION_LESS;
|
||||||
|
case TK_LE:
|
||||||
|
return TSDB_RELATION_LESS_EQUAL;
|
||||||
|
case TK_GT:
|
||||||
|
return TSDB_RELATION_GREATER;
|
||||||
|
case TK_GE:
|
||||||
|
return TSDB_RELATION_GREATER_EQUAL;
|
||||||
|
case TK_NE:
|
||||||
|
return TSDB_RELATION_NOT_EQUAL;
|
||||||
|
case TK_AND:
|
||||||
|
return TSDB_RELATION_AND;
|
||||||
|
case TK_OR:
|
||||||
|
return TSDB_RELATION_OR;
|
||||||
|
case TK_EQ:
|
||||||
|
return TSDB_RELATION_EQUAL;
|
||||||
|
case TK_PLUS:
|
||||||
|
return TSDB_BINARY_OP_ADD;
|
||||||
|
case TK_MINUS:
|
||||||
|
return TSDB_BINARY_OP_SUBTRACT;
|
||||||
|
case TK_STAR:
|
||||||
|
return TSDB_BINARY_OP_MULTIPLY;
|
||||||
|
case TK_SLASH:
|
||||||
|
case TK_DIVIDE:
|
||||||
|
return TSDB_BINARY_OP_DIVIDE;
|
||||||
|
case TK_REM:
|
||||||
|
return TSDB_BINARY_OP_REMAINDER;
|
||||||
|
case TK_LIKE:
|
||||||
|
return TSDB_RELATION_LIKE;
|
||||||
|
case TK_ISNULL:
|
||||||
|
return TSDB_RELATION_ISNULL;
|
||||||
|
case TK_NOTNULL:
|
||||||
|
return TSDB_RELATION_NOTNULL;
|
||||||
|
default: { return 0; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used during parsing query sql. Since the query sql usually small in length, error position
|
* Used during parsing query sql. Since the query sql usually small in length, error position
|
||||||
* is not needed in the final error message.
|
* is not needed in the final error message.
|
||||||
|
@ -1725,7 +1767,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t functionID = 0;
|
int16_t functionID = 0;
|
||||||
if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
||||||
return TSDB_CODE_TSC_INVALID_SQL;
|
return TSDB_CODE_TSC_INVALID_SQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1861,7 +1903,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
int32_t intermediateResSize = 0;
|
int32_t intermediateResSize = 0;
|
||||||
|
|
||||||
int16_t functionID = 0;
|
int16_t functionID = 0;
|
||||||
if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
||||||
return TSDB_CODE_TSC_INVALID_SQL;
|
return TSDB_CODE_TSC_INVALID_SQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1932,7 +1974,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
bool requireAllFields = (pItem->pNode->pParam == NULL);
|
bool requireAllFields = (pItem->pNode->pParam == NULL);
|
||||||
|
|
||||||
int16_t functionID = 0;
|
int16_t functionID = 0;
|
||||||
if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
||||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
|
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2121,7 +2163,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
* for dp = 100, it is max,
|
* for dp = 100, it is max,
|
||||||
*/
|
*/
|
||||||
int16_t functionId = 0;
|
int16_t functionId = 0;
|
||||||
if (changeFunctionID(optr, &functionId) != TSDB_CODE_SUCCESS) {
|
if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) {
|
||||||
return TSDB_CODE_TSC_INVALID_SQL;
|
return TSDB_CODE_TSC_INVALID_SQL;
|
||||||
}
|
}
|
||||||
tscInsertPrimaryTSSourceColumn(pQueryInfo, &index);
|
tscInsertPrimaryTSSourceColumn(pQueryInfo, &index);
|
||||||
|
@ -2138,7 +2180,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t functionId = 0;
|
int16_t functionId = 0;
|
||||||
if (changeFunctionID(optr, &functionId) != TSDB_CODE_SUCCESS) {
|
if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) {
|
||||||
return TSDB_CODE_TSC_INVALID_SQL;
|
return TSDB_CODE_TSC_INVALID_SQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2397,7 +2439,7 @@ int32_t getColumnIndexByName(SSqlCmd* pCmd, const SStrToken* pToken, SQueryInfo*
|
||||||
return doGetColumnIndexByName(pCmd, &tmpToken, pQueryInfo, pIndex);
|
return doGetColumnIndexByName(pCmd, &tmpToken, pQueryInfo, pIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t changeFunctionID(int32_t optr, int16_t* functionId) {
|
int32_t convertFunctionId(int32_t optr, int16_t* functionId) {
|
||||||
switch (optr) {
|
switch (optr) {
|
||||||
case TK_COUNT:
|
case TK_COUNT:
|
||||||
*functionId = TSDB_FUNC_COUNT;
|
*functionId = TSDB_FUNC_COUNT;
|
||||||
|
@ -6535,7 +6577,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
|
||||||
(*pExpr)->_node.pRight = pRight;
|
(*pExpr)->_node.pRight = pRight;
|
||||||
|
|
||||||
SStrToken t = {.type = pSqlExpr->nSQLOptr};
|
SStrToken t = {.type = pSqlExpr->nSQLOptr};
|
||||||
(*pExpr)->_node.optr = getBinaryExprOptr(&t);
|
(*pExpr)->_node.optr = convertOptr(&t);
|
||||||
|
|
||||||
assert((*pExpr)->_node.optr != 0);
|
assert((*pExpr)->_node.optr != 0);
|
||||||
|
|
||||||
|
|
|
@ -130,16 +130,6 @@ SSchema* tscGetColumnSchemaById(STableMeta* pTableMeta, int16_t colId) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SSchema tscGetTbnameColumnSchema() {
|
|
||||||
struct SSchema s = {
|
|
||||||
.colId = TSDB_TBNAME_COLUMN_INDEX,
|
|
||||||
.type = TSDB_DATA_TYPE_BINARY,
|
|
||||||
.bytes = TSDB_TABLE_NAME_LEN
|
|
||||||
};
|
|
||||||
|
|
||||||
strcpy(s.name, TSQL_TBNAME_L);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
static void tscInitCorVgroupInfo(SCorVgroupInfo *corVgroupInfo, SVgroupInfo *vgroupInfo) {
|
static void tscInitCorVgroupInfo(SCorVgroupInfo *corVgroupInfo, SVgroupInfo *vgroupInfo) {
|
||||||
corVgroupInfo->version = 0;
|
corVgroupInfo->version = 0;
|
||||||
corVgroupInfo->inUse = 0;
|
corVgroupInfo->inUse = 0;
|
||||||
|
|
|
@ -35,6 +35,10 @@ bool tscValidateTableNameLength(size_t len);
|
||||||
|
|
||||||
SColumnFilterInfo* tscFilterInfoClone(const SColumnFilterInfo* src, int32_t numOfFilters);
|
SColumnFilterInfo* tscFilterInfoClone(const SColumnFilterInfo* src, int32_t numOfFilters);
|
||||||
|
|
||||||
// int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision);
|
/**
|
||||||
|
* get the schema for the "tbname" column. it is a built column
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SSchema tscGetTbnameColumnSchema();
|
||||||
|
|
||||||
#endif // TDENGINE_NAME_H
|
#endif // TDENGINE_NAME_H
|
||||||
|
|
|
@ -188,3 +188,14 @@ void extractTableNameFromToken(SStrToken* pToken, SStrToken* pTable) {
|
||||||
pToken->z = r;
|
pToken->z = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSchema tscGetTbnameColumnSchema() {
|
||||||
|
struct SSchema s = {
|
||||||
|
.colId = TSDB_TBNAME_COLUMN_INDEX,
|
||||||
|
.type = TSDB_DATA_TYPE_BINARY,
|
||||||
|
.bytes = TSDB_TABLE_NAME_LEN
|
||||||
|
};
|
||||||
|
|
||||||
|
strcpy(s.name, TSQL_TBNAME_L);
|
||||||
|
return s;
|
||||||
|
}
|
|
@ -81,14 +81,13 @@ void tExprTreeTraverse(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, S
|
||||||
void tExprTreeCalcTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput, void *param, int32_t order,
|
void tExprTreeCalcTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput, void *param, int32_t order,
|
||||||
char *(*cb)(void *, const char*, int32_t));
|
char *(*cb)(void *, const char*, int32_t));
|
||||||
|
|
||||||
uint8_t getBinaryExprOptr(SStrToken *pToken);
|
|
||||||
|
|
||||||
void tExprNodeDestroy(tExprNode *pNode, void (*fp)(void *));
|
|
||||||
void exprTreeToBinary(SBufferWriter* bw, tExprNode* pExprTree);
|
|
||||||
|
|
||||||
tExprNode* exprTreeFromBinary(const void* data, size_t size);
|
tExprNode* exprTreeFromBinary(const void* data, size_t size);
|
||||||
tExprNode* exprTreeFromTableName(const char* tbnameCond);
|
tExprNode* exprTreeFromTableName(const char* tbnameCond);
|
||||||
|
|
||||||
|
void exprTreeToBinary(SBufferWriter* bw, tExprNode* pExprTree);
|
||||||
|
|
||||||
|
void tExprNodeDestroy(tExprNode *pNode, void (*fp)(void *));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -309,9 +309,6 @@ void tSQLSetColumnType(TAOS_FIELD *pField, SStrToken *pToken);
|
||||||
|
|
||||||
void *ParseAlloc(void *(*mallocProc)(size_t));
|
void *ParseAlloc(void *(*mallocProc)(size_t));
|
||||||
|
|
||||||
// convert the sql filter expression into binary data
|
|
||||||
int32_t tSQLExprToBinary(tSQLExpr* pExpr, SStringBuilder* sb);
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TSQL_NODE_TYPE_EXPR = 0x1,
|
TSQL_NODE_TYPE_EXPR = 0x1,
|
||||||
TSQL_NODE_TYPE_ID = 0x2,
|
TSQL_NODE_TYPE_ID = 0x2,
|
||||||
|
|
|
@ -13,12 +13,10 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "qAst.h"
|
#include "qAst.h"
|
||||||
#include "qSqlparser.h"
|
|
||||||
#include "qSyntaxtreefunction.h"
|
#include "qSyntaxtreefunction.h"
|
||||||
#include "taosdef.h"
|
#include "taosdef.h"
|
||||||
#include "taosmsg.h"
|
#include "taosmsg.h"
|
||||||
|
@ -30,200 +28,19 @@
|
||||||
#include "tskiplist.h"
|
#include "tskiplist.h"
|
||||||
#include "tsqlfunction.h"
|
#include "tsqlfunction.h"
|
||||||
#include "tstoken.h"
|
#include "tstoken.h"
|
||||||
#include "ttokendef.h"
|
#include "tschemautil.h"
|
||||||
#include "tulog.h"
|
|
||||||
|
|
||||||
/*
|
typedef struct {
|
||||||
*
|
char* v;
|
||||||
* @date 2018-2-15
|
int32_t optr;
|
||||||
* @version 0.2 operation for column filter
|
} SEndPoint;
|
||||||
*
|
|
||||||
* @Description parse tag query expression to build ast
|
|
||||||
* ver 0.2, filter the result on first column with high priority to limit the candidate set
|
|
||||||
* ver 0.3, pipeline filter in the form of: (a+2)/9 > 14
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static tExprNode *tExprNodeCreate(SSchema *pSchema, int32_t numOfCols, SStrToken *pToken);
|
|
||||||
|
|
||||||
static tExprNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *str, int32_t *i);
|
typedef struct {
|
||||||
static void destroySyntaxTree(tExprNode *);
|
SEndPoint* start;
|
||||||
|
SEndPoint* end;
|
||||||
|
} SQueryCond;
|
||||||
|
|
||||||
static uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tExprNode *pLeft, const tExprNode *pRight);
|
static uint8_t UNUSED_FUNC isQueryOnPrimaryKey(const char *primaryColumnName, const tExprNode *pLeft, const tExprNode *pRight) {
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the filter value type on the right hand side based on the column id on the left hand side,
|
|
||||||
* the filter value type must be identical to field type for relational operation
|
|
||||||
* As for binary arithmetic operation, it is not necessary to do so.
|
|
||||||
*/
|
|
||||||
static void reviseBinaryExprIfNecessary(tExprNode **pLeft, tExprNode **pRight, uint8_t *optr) {
|
|
||||||
if (*optr >= TSDB_RELATION_LESS && *optr <= TSDB_RELATION_LIKE) {
|
|
||||||
// make sure that the type of data on both sides of relational comparision are identical
|
|
||||||
if ((*pLeft)->nodeType == TSQL_NODE_VALUE) {
|
|
||||||
tVariantTypeSetType((*pLeft)->pVal, (*pRight)->pSchema->type);
|
|
||||||
} else if ((*pRight)->nodeType == TSQL_NODE_VALUE) {
|
|
||||||
tVariantTypeSetType((*pRight)->pVal, (*pLeft)->pSchema->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (*optr >= TSDB_BINARY_OP_ADD && *optr <= TSDB_BINARY_OP_REMAINDER) {
|
|
||||||
if ((*pLeft)->nodeType == TSQL_NODE_VALUE) {
|
|
||||||
/* convert to int/bigint may cause the precision loss */
|
|
||||||
tVariantTypeSetType((*pLeft)->pVal, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
} else if ((*pRight)->nodeType == TSQL_NODE_VALUE) {
|
|
||||||
/* convert to int/bigint may cause the precision loss */
|
|
||||||
tVariantTypeSetType((*pRight)->pVal, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* for expressions that are suitable for switch principle,
|
|
||||||
* switch left and left and right hand side in expr if possible
|
|
||||||
*/
|
|
||||||
if ((*pLeft)->nodeType == TSQL_NODE_VALUE && (*pRight)->nodeType == TSQL_NODE_COL) {
|
|
||||||
if (*optr >= TSDB_RELATION_GREATER && *optr <= TSDB_RELATION_GREATER_EQUAL && *optr != TSDB_RELATION_EQUAL) {
|
|
||||||
SWAP(*pLeft, *pRight, tExprNode *);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (*optr) {
|
|
||||||
case TSDB_RELATION_GREATER:
|
|
||||||
(*optr) = TSDB_RELATION_LESS;
|
|
||||||
break;
|
|
||||||
case TSDB_RELATION_LESS:
|
|
||||||
(*optr) = TSDB_RELATION_GREATER;
|
|
||||||
break;
|
|
||||||
case TSDB_RELATION_GREATER_EQUAL:
|
|
||||||
(*optr) = TSDB_RELATION_LESS_EQUAL;
|
|
||||||
break;
|
|
||||||
case TSDB_RELATION_LESS_EQUAL:
|
|
||||||
(*optr) = TSDB_RELATION_GREATER_EQUAL;
|
|
||||||
break;
|
|
||||||
default:;
|
|
||||||
// for other type of operations, do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static tExprNode *tExprNodeCreate(SSchema *pSchema, int32_t numOfCols, SStrToken *pToken) {
|
|
||||||
/* if the token is not a value, return false */
|
|
||||||
if (pToken->type == TK_RP || (pToken->type != TK_INTEGER && pToken->type != TK_FLOAT && pToken->type != TK_ID &&
|
|
||||||
pToken->type != TK_TBNAME && pToken->type != TK_STRING && pToken->type != TK_BOOL)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nodeSize = sizeof(tExprNode);
|
|
||||||
tExprNode *pNode = NULL;
|
|
||||||
|
|
||||||
if (pToken->type == TK_ID || pToken->type == TK_TBNAME) {
|
|
||||||
int32_t i = 0;
|
|
||||||
if (pToken->type == TK_ID) {
|
|
||||||
do {
|
|
||||||
SStrToken tableToken = {0};
|
|
||||||
extractTableNameFromToken(pToken, &tableToken);
|
|
||||||
|
|
||||||
size_t len = strlen(pSchema[i].name);
|
|
||||||
if (strncmp(pToken->z, pSchema[i].name, pToken->n) == 0 && pToken->n == len) break;
|
|
||||||
} while (++i < numOfCols);
|
|
||||||
|
|
||||||
if (i == numOfCols) { // column name is not valid, parse the expression failed
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeSize += sizeof(SSchema);
|
|
||||||
|
|
||||||
pNode = calloc(1, nodeSize);
|
|
||||||
pNode->pSchema = (struct SSchema *)((char *)pNode + sizeof(tExprNode));
|
|
||||||
pNode->nodeType = TSQL_NODE_COL;
|
|
||||||
|
|
||||||
if (pToken->type == TK_ID) {
|
|
||||||
memcpy(pNode->pSchema, &pSchema[i], sizeof(SSchema));
|
|
||||||
} else {
|
|
||||||
pNode->pSchema->type = TSDB_DATA_TYPE_BINARY;
|
|
||||||
pNode->pSchema->bytes = TSDB_TABLE_NAME_LEN - 1;
|
|
||||||
strcpy(pNode->pSchema->name, TSQL_TBNAME_L);
|
|
||||||
pNode->pSchema->colId = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
nodeSize += sizeof(tVariant);
|
|
||||||
pNode = calloc(1, nodeSize);
|
|
||||||
pNode->pVal = (tVariant *)((char *)pNode + sizeof(tExprNode));
|
|
||||||
|
|
||||||
toTSDBType(pToken->type);
|
|
||||||
tVariantCreate(pNode->pVal, pToken);
|
|
||||||
pNode->nodeType = TSQL_NODE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getBinaryExprOptr(SStrToken *pToken) {
|
|
||||||
switch (pToken->type) {
|
|
||||||
case TK_LT:
|
|
||||||
return TSDB_RELATION_LESS;
|
|
||||||
case TK_LE:
|
|
||||||
return TSDB_RELATION_LESS_EQUAL;
|
|
||||||
case TK_GT:
|
|
||||||
return TSDB_RELATION_GREATER;
|
|
||||||
case TK_GE:
|
|
||||||
return TSDB_RELATION_GREATER_EQUAL;
|
|
||||||
case TK_NE:
|
|
||||||
return TSDB_RELATION_NOT_EQUAL;
|
|
||||||
case TK_AND:
|
|
||||||
return TSDB_RELATION_AND;
|
|
||||||
case TK_OR:
|
|
||||||
return TSDB_RELATION_OR;
|
|
||||||
case TK_EQ:
|
|
||||||
return TSDB_RELATION_EQUAL;
|
|
||||||
case TK_PLUS:
|
|
||||||
return TSDB_BINARY_OP_ADD;
|
|
||||||
case TK_MINUS:
|
|
||||||
return TSDB_BINARY_OP_SUBTRACT;
|
|
||||||
case TK_STAR:
|
|
||||||
return TSDB_BINARY_OP_MULTIPLY;
|
|
||||||
case TK_SLASH:
|
|
||||||
case TK_DIVIDE:
|
|
||||||
return TSDB_BINARY_OP_DIVIDE;
|
|
||||||
case TK_REM:
|
|
||||||
return TSDB_BINARY_OP_REMAINDER;
|
|
||||||
case TK_LIKE:
|
|
||||||
return TSDB_RELATION_LIKE;
|
|
||||||
case TK_ISNULL:
|
|
||||||
return TSDB_RELATION_ISNULL;
|
|
||||||
case TK_NOTNULL:
|
|
||||||
return TSDB_RELATION_NOTNULL;
|
|
||||||
default: { return 0; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// previous generated expr is reduced as the left child
|
|
||||||
static tExprNode *parseRemainStr(char *pstr, tExprNode *pExpr, SSchema *pSchema, int32_t optr,
|
|
||||||
int32_t numOfCols, int32_t *i) {
|
|
||||||
// set the previous generated node as the left child of new root
|
|
||||||
pExpr->nodeType = TSQL_NODE_EXPR;
|
|
||||||
|
|
||||||
// remain is the right child
|
|
||||||
tExprNode *pRight = createSyntaxTree(pSchema, numOfCols, pstr, i);
|
|
||||||
if (pRight == NULL || (pRight->nodeType == TSQL_NODE_COL && pExpr->nodeType != TSQL_NODE_VALUE) ||
|
|
||||||
(pExpr->nodeType == TSQL_NODE_VALUE && pRight->nodeType != TSQL_NODE_COL)) {
|
|
||||||
tExprNodeDestroy(pExpr, NULL);
|
|
||||||
tExprNodeDestroy(pRight, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tExprNode *pNewExpr = (tExprNode *)calloc(1, sizeof(tExprNode));
|
|
||||||
uint8_t k = optr;
|
|
||||||
reviseBinaryExprIfNecessary(&pExpr, &pRight, &k);
|
|
||||||
pNewExpr->_node.pLeft = pExpr;
|
|
||||||
pNewExpr->_node.pRight = pRight;
|
|
||||||
pNewExpr->_node.optr = k;
|
|
||||||
|
|
||||||
pNewExpr->_node.hasPK = isQueryOnPrimaryKey(pSchema[0].name, pExpr, pRight);
|
|
||||||
pNewExpr->nodeType = TSQL_NODE_EXPR;
|
|
||||||
|
|
||||||
return pNewExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tExprNode *pLeft, const tExprNode *pRight) {
|
|
||||||
if (pLeft->nodeType == TSQL_NODE_COL) {
|
if (pLeft->nodeType == TSQL_NODE_COL) {
|
||||||
// if left node is the primary column,return true
|
// if left node is the primary column,return true
|
||||||
return (strcmp(primaryColumnName, pLeft->pSchema->name) == 0) ? 1 : 0;
|
return (strcmp(primaryColumnName, pLeft->pSchema->name) == 0) ? 1 : 0;
|
||||||
|
@ -236,103 +53,6 @@ uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tExprNode *pLef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static tExprNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *str, int32_t *i) {
|
|
||||||
SStrToken t0 = tStrGetToken(str, i, false, 0, NULL);
|
|
||||||
if (t0.n == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tExprNode *pLeft = NULL;
|
|
||||||
if (t0.type == TK_LP) { // start new left child branch
|
|
||||||
pLeft = createSyntaxTree(pSchema, numOfCols, str, i);
|
|
||||||
} else {
|
|
||||||
if (t0.type == TK_RP) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pLeft = tExprNodeCreate(pSchema, numOfCols, &t0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pLeft == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
t0 = tStrGetToken(str, i, false, 0, NULL);
|
|
||||||
if (t0.n == 0 || t0.type == TK_RP) {
|
|
||||||
if (pLeft->nodeType != TSQL_NODE_EXPR) { // if left is not the expr, it is not a legal expr
|
|
||||||
tExprNodeDestroy(pLeft, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the operator of expr
|
|
||||||
uint8_t optr = getBinaryExprOptr(&t0);
|
|
||||||
if (optr == 0) {
|
|
||||||
uError("not support binary operator:%d", t0.type);
|
|
||||||
tExprNodeDestroy(pLeft, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(pLeft != NULL);
|
|
||||||
tExprNode *pRight = NULL;
|
|
||||||
|
|
||||||
if (t0.type == TK_AND || t0.type == TK_OR || t0.type == TK_LP) {
|
|
||||||
pRight = createSyntaxTree(pSchema, numOfCols, str, i);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* In case that pLeft is a field identification,
|
|
||||||
* we parse the value in expression according to queried field type,
|
|
||||||
* if we do not get the information, in case of value of field presented first,
|
|
||||||
* we revised the value after the binary expression is completed.
|
|
||||||
*/
|
|
||||||
t0 = tStrGetToken(str, i, true, 0, NULL);
|
|
||||||
if (t0.n == 0) {
|
|
||||||
tExprNodeDestroy(pLeft, NULL); // illegal expression
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t0.type == TK_LP) {
|
|
||||||
pRight = createSyntaxTree(pSchema, numOfCols, str, i);
|
|
||||||
} else {
|
|
||||||
pRight = tExprNodeCreate(pSchema, numOfCols, &t0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pRight == NULL) {
|
|
||||||
tExprNodeDestroy(pLeft, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create binary expr as the child of new parent node */
|
|
||||||
tExprNode *pExpr = (tExprNode *)calloc(1, sizeof(tExprNode));
|
|
||||||
reviseBinaryExprIfNecessary(&pLeft, &pRight, &optr);
|
|
||||||
|
|
||||||
pExpr->_node.hasPK = isQueryOnPrimaryKey(pSchema[0].name, pLeft, pRight);
|
|
||||||
pExpr->_node.pLeft = pLeft;
|
|
||||||
pExpr->_node.pRight = pRight;
|
|
||||||
pExpr->_node.optr = optr;
|
|
||||||
|
|
||||||
t0 = tStrGetToken(str, i, true, 0, NULL);
|
|
||||||
|
|
||||||
if (t0.n == 0 || t0.type == TK_RP) {
|
|
||||||
pExpr->nodeType = TSQL_NODE_EXPR;
|
|
||||||
return pExpr;
|
|
||||||
} else {
|
|
||||||
uint8_t localOptr = getBinaryExprOptr(&t0);
|
|
||||||
if (localOptr == 0) {
|
|
||||||
uError("not support binary operator:%d", t0.type);
|
|
||||||
free(pExpr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return parseRemainStr(str, pExpr, pSchema, localOptr, numOfCols, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void UNUSED_FUNC destroySyntaxTree(tExprNode *pNode) { tExprNodeDestroy(pNode, NULL); }
|
|
||||||
|
|
||||||
void tExprNodeDestroy(tExprNode *pNode, void (*fp)(void *)) {
|
void tExprNodeDestroy(tExprNode *pNode, void (*fp)(void *)) {
|
||||||
if (pNode == NULL) {
|
if (pNode == NULL) {
|
||||||
return;
|
return;
|
||||||
|
@ -372,16 +92,6 @@ void tExprTreeDestroy(tExprNode **pExpr, void (*fp)(void *)) {
|
||||||
*pExpr = NULL;
|
*pExpr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* v;
|
|
||||||
int32_t optr;
|
|
||||||
} SEndPoint;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SEndPoint* start;
|
|
||||||
SEndPoint* end;
|
|
||||||
} SQueryCond;
|
|
||||||
|
|
||||||
// todo check for malloc failure
|
// todo check for malloc failure
|
||||||
static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
|
static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
|
||||||
int32_t optr = queryColInfo->optr;
|
int32_t optr = queryColInfo->optr;
|
||||||
|
@ -395,13 +105,10 @@ static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
|
||||||
pCond->end = calloc(1, sizeof(SEndPoint));
|
pCond->end = calloc(1, sizeof(SEndPoint));
|
||||||
pCond->end->optr = queryColInfo->optr;
|
pCond->end->optr = queryColInfo->optr;
|
||||||
pCond->end->v = queryColInfo->q;
|
pCond->end->v = queryColInfo->q;
|
||||||
} else if (optr == TSDB_RELATION_IN) {
|
} else if (optr == TSDB_RELATION_IN || optr == TSDB_RELATION_LIKE) {
|
||||||
printf("relation is in\n");
|
|
||||||
assert(0);
|
|
||||||
} else if (optr == TSDB_RELATION_LIKE) {
|
|
||||||
printf("relation is like\n");
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,99 +236,6 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
|
||||||
tSkipListDestroyIter(iter);
|
tSkipListDestroyIter(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t merge(SArray *pLeft, SArray *pRight, SArray *pFinalRes) {
|
|
||||||
// assert(pFinalRes->pRes == 0);
|
|
||||||
//
|
|
||||||
// pFinalRes->pRes = calloc((size_t)(pLeft->num + pRight->num), POINTER_BYTES);
|
|
||||||
// pFinalRes->num = 0;
|
|
||||||
//
|
|
||||||
// // sort according to address
|
|
||||||
// tSkipListNode **pLeftNodes = (tSkipListNode **)pLeft->pRes;
|
|
||||||
// qsort(pLeftNodes, pLeft->num, sizeof(pLeft->pRes[0]), compareByAddr);
|
|
||||||
//
|
|
||||||
// tSkipListNode **pRightNodes = (tSkipListNode **)pRight->pRes;
|
|
||||||
// qsort(pRightNodes, pRight->num, sizeof(pRight->pRes[0]), compareByAddr);
|
|
||||||
//
|
|
||||||
// int32_t i = 0, j = 0;
|
|
||||||
//
|
|
||||||
// // merge two sorted arrays in O(n) time
|
|
||||||
// while (i < pLeft->num && j < pRight->num) {
|
|
||||||
// int64_t ret = (int64_t)pLeftNodes[i] - (int64_t)pRightNodes[j];
|
|
||||||
//
|
|
||||||
// if (ret < 0) {
|
|
||||||
// pFinalRes->pRes[pFinalRes->num++] = pLeftNodes[i++];
|
|
||||||
// } else if (ret > 0) {
|
|
||||||
// pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j++];
|
|
||||||
// } else { // pNode->key > pkey[i]
|
|
||||||
// pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j++];
|
|
||||||
// i++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// while (i < pLeft->num) {
|
|
||||||
// pFinalRes->pRes[pFinalRes->num++] = pLeftNodes[i++];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// while (j < pRight->num) {
|
|
||||||
// pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j++];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return pFinalRes->num;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t intersect(SArray *pLeft, SArray *pRight, SArray *pFinalRes) {
|
|
||||||
// int64_t num = MIN(pLeft->num, pRight->num);
|
|
||||||
//
|
|
||||||
// assert(pFinalRes->pRes == 0);
|
|
||||||
//
|
|
||||||
// pFinalRes->pRes = calloc(num, POINTER_BYTES);
|
|
||||||
// pFinalRes->num = 0;
|
|
||||||
//
|
|
||||||
// // sort according to address
|
|
||||||
// tSkipListNode **pLeftNodes = (tSkipListNode **)pLeft->pRes;
|
|
||||||
// qsort(pLeftNodes, pLeft->num, sizeof(pLeft->pRes[0]), compareByAddr);
|
|
||||||
//
|
|
||||||
// tSkipListNode **pRightNodes = (tSkipListNode **)pRight->pRes;
|
|
||||||
// qsort(pRightNodes, pRight->num, sizeof(pRight->pRes[0]), compareByAddr);
|
|
||||||
//
|
|
||||||
// int32_t i = 0, j = 0;
|
|
||||||
// // merge two sorted arrays in O(n) time
|
|
||||||
// while (i < pLeft->num && j < pRight->num) {
|
|
||||||
// int64_t ret = (int64_t)pLeftNodes[i] - (int64_t)pRightNodes[j];
|
|
||||||
//
|
|
||||||
// if (ret < 0) {
|
|
||||||
// i++;
|
|
||||||
// } else if (ret > 0) {
|
|
||||||
// j++;
|
|
||||||
// } else { // pNode->key > pkey[i]
|
|
||||||
// pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j];
|
|
||||||
// i++;
|
|
||||||
// j++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return pFinalRes->num;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* traverse the result and apply the function to each item to check if the item is qualified or not
|
|
||||||
*/
|
|
||||||
static UNUSED_FUNC void tArrayTraverse(tExprNode *pExpr, __result_filter_fn_t fp, SArray *pResult) {
|
|
||||||
assert(pExpr->_node.pLeft->nodeType == TSQL_NODE_COL && pExpr->_node.pRight->nodeType == TSQL_NODE_VALUE && fp != NULL);
|
|
||||||
|
|
||||||
// scan the result array list and check for each item in the list
|
|
||||||
for (int32_t i = 0; i < taosArrayGetSize(pResult); ++i) {
|
|
||||||
void* item = taosArrayGet(pResult, i);
|
|
||||||
if (fp(item, pExpr->_node.info)) {
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
taosArrayRemove(pResult, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool filterItem(tExprNode *pExpr, const void *pItem, SExprTraverseSupp *param) {
|
static bool filterItem(tExprNode *pExpr, const void *pItem, SExprTraverseSupp *param) {
|
||||||
tExprNode *pLeft = pExpr->_node.pLeft;
|
tExprNode *pLeft = pExpr->_node.pLeft;
|
||||||
tExprNode *pRight = pExpr->_node.pRight;
|
tExprNode *pRight = pExpr->_node.pRight;
|
||||||
|
@ -649,32 +263,6 @@ static bool filterItem(tExprNode *pExpr, const void *pItem, SExprTraverseSupp *p
|
||||||
return param->nodeFilterFn(pItem, pExpr->_node.info);
|
return param->nodeFilterFn(pItem, pExpr->_node.info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the filter expression on non-indexed tag columns to each element in the result list, which is generated
|
|
||||||
* by filtering on indexed tag column. So the whole result set only needs to be iterated once to generate
|
|
||||||
* result that is satisfied to the filter expression, no matter how the filter expression consisting of.
|
|
||||||
*
|
|
||||||
* @param pExpr filter expression on non-indexed tag columns.
|
|
||||||
* @param pResult results from filter on the indexed tag column, which is usually the first tag column
|
|
||||||
* @param pSchema tag schemas
|
|
||||||
* @param fp filter callback function
|
|
||||||
*/
|
|
||||||
static UNUSED_FUNC void exprTreeTraverseImpl(tExprNode *pExpr, SArray *pResult, SExprTraverseSupp *param) {
|
|
||||||
size_t size = taosArrayGetSize(pResult);
|
|
||||||
|
|
||||||
SArray* array = taosArrayInit(size, POINTER_BYTES);
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
|
||||||
void *pItem = taosArrayGetP(pResult, i);
|
|
||||||
|
|
||||||
if (filterItem(pExpr, pItem, param)) {
|
|
||||||
taosArrayPush(array, &pItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayCopy(pResult, array);
|
|
||||||
taosArrayDestroy(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tSQLBinaryTraverseOnSkipList(tExprNode *pExpr, SArray *pResult, SSkipList *pSkipList, SExprTraverseSupp *param ) {
|
static void tSQLBinaryTraverseOnSkipList(tExprNode *pExpr, SArray *pResult, SSkipList *pSkipList, SExprTraverseSupp *param ) {
|
||||||
SSkipListIterator* iter = tSkipListCreateIter(pSkipList);
|
SSkipListIterator* iter = tSkipListCreateIter(pSkipList);
|
||||||
|
|
||||||
|
@ -972,6 +560,7 @@ tExprNode* exprTreeFromBinary(const void* data, size_t size) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SBufferReader br = tbufInitReader(data, size, false);
|
SBufferReader br = tbufInitReader(data, size, false);
|
||||||
return exprTreeFromBinaryImpl(&br);
|
return exprTreeFromBinaryImpl(&br);
|
||||||
}
|
}
|
||||||
|
@ -995,10 +584,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) {
|
||||||
SSchema* pSchema = exception_calloc(1, sizeof(SSchema));
|
SSchema* pSchema = exception_calloc(1, sizeof(SSchema));
|
||||||
left->pSchema = pSchema;
|
left->pSchema = pSchema;
|
||||||
|
|
||||||
pSchema->type = TSDB_DATA_TYPE_BINARY;
|
*pSchema = tscGetTbnameColumnSchema();
|
||||||
pSchema->bytes = TSDB_TABLE_NAME_LEN - 1;
|
|
||||||
strcpy(pSchema->name, TSQL_TBNAME_L);
|
|
||||||
pSchema->colId = -1;
|
|
||||||
|
|
||||||
tExprNode* right = exception_calloc(1, sizeof(tExprNode));
|
tExprNode* right = exception_calloc(1, sizeof(tExprNode));
|
||||||
expr->_node.pRight = right;
|
expr->_node.pRight = right;
|
||||||
|
|
Loading…
Reference in New Issue