diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 502d044d7540169497b682df96424ca3304f4668..60a8ff894ff98fa1b9021c73dbe57c246d88c86e 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -133,6 +133,7 @@ bool tscIsProjectionQuery(SQueryInfo* pQueryInfo); bool tscIsTwoStageSTableQuery(SQueryInfo* pQueryInfo, int32_t tableIndex); bool tscQueryTags(SQueryInfo* pQueryInfo); bool tscMultiRoundQuery(SQueryInfo* pQueryInfo, int32_t tableIndex); +bool tscQueryBlockInfo(SQueryInfo* pQueryInfo); SSqlExpr* tscAddFuncInSelectClause(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, SColumnIndex* pIndex, SSchema* pColSchema, int16_t colType); diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 23fb0ab67cded77ff737fac4246343486e80eb95..a44b0c46ba7920c2483c4baa3b34bc37f06bdee7 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -100,6 +100,10 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SLocalMerger *pReducer, tOrderDescr } else if (functionId == TSDB_FUNC_APERCT) { pCtx->param[0].i64 = pExpr->param[0].i64; pCtx->param[0].nType = pExpr->param[0].nType; + } else if (functionId == TSDB_FUNC_BLKINFO) { + pCtx->param[0].i64 = pExpr->param[0].i64; + pCtx->param[0].nType = pExpr->param[0].nType; + pCtx->numOfParams = 1; } pCtx->interBufBytes = pExpr->interBytes; @@ -951,10 +955,10 @@ static void doFillResult(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool doneOutp // todo extract function int64_t actualETime = (pQueryInfo->order.order == TSDB_ORDER_ASC)? pQueryInfo->window.ekey: pQueryInfo->window.skey; - tFilePage **pResPages = malloc(POINTER_BYTES * pQueryInfo->fieldsInfo.numOfOutput); + void** pResPages = malloc(POINTER_BYTES * pQueryInfo->fieldsInfo.numOfOutput); for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i); - pResPages[i] = calloc(1, sizeof(tFilePage) + pField->bytes * pLocalMerge->resColModel->capacity); + pResPages[i] = calloc(1, pField->bytes * pLocalMerge->resColModel->capacity); } while (1) { @@ -966,7 +970,7 @@ static void doFillResult(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool doneOutp if (pQueryInfo->limit.offset > 0) { for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i); - memmove(pResPages[i]->data, pResPages[i]->data + pField->bytes * pQueryInfo->limit.offset, + memmove(pResPages[i], ((char*)pResPages[i]) + pField->bytes * pQueryInfo->limit.offset, (size_t)(newRows * pField->bytes)); } } @@ -1010,7 +1014,7 @@ static void doFillResult(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool doneOutp int32_t offset = 0; for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i); - memcpy(pRes->data + offset * pRes->numOfRows, pResPages[i]->data, (size_t)(pField->bytes * pRes->numOfRows)); + memcpy(pRes->data + offset * pRes->numOfRows, pResPages[i], (size_t)(pField->bytes * pRes->numOfRows)); offset += pField->bytes; } diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 7219e56cb9c8cfb035e44b5337907688f90f29c8..34cccc4c5f659a8610323cfac44f1f794e9a954f 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -75,7 +75,6 @@ static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int3 static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes, int8_t type, char* fieldName, SSqlExpr* pSqlExpr); -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, bool intervalQuery); @@ -176,11 +175,11 @@ static uint8_t convertOptr(SStrToken *pToken) { static bool validateDebugFlag(int32_t v) { const static int validFlag[] = {131, 135, 143}; - + for (int i = 0; i < tListLen(validFlag); i++) { if (v == validFlag[i]) { return true; - } + } } return false; } @@ -584,8 +583,8 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) { SStrToken* t1 = taosArrayGet(pMiscInfo->a, 1); pCmd->payload[t->n] = ' '; // add sep strncpy(&pCmd->payload[t->n + 1], t1->z, t1->n); - } - return TSDB_CODE_SUCCESS; + } + return TSDB_CODE_SUCCESS; } case TSDB_SQL_CREATE_TABLE: { @@ -1537,6 +1536,7 @@ bool isValidDistinctSql(SQueryInfo* pQueryInfo) { } return false; } + int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool intervalQuery) { assert(pSelection != NULL && pCmd != NULL); @@ -1550,6 +1550,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel if (pQueryInfo->colList == NULL) { pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); } + bool hasDistinct = false; for (int32_t i = 0; i < pSelection->nExpr; ++i) { int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); @@ -1558,26 +1559,25 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel if (hasDistinct == false) { hasDistinct = (pItem->distinct == true); } - // project on all fields - int32_t optr = pItem->pNode->nSQLOptr; - if (optr == TK_ALL || optr == TK_ID || optr == TK_STRING || optr == TK_INTEGER || optr == TK_FLOAT) { - // it is actually a function, but the function name is invalid - if (pItem->pNode->nSQLOptr == TK_ID && (pItem->pNode->colInfo.z == NULL && pItem->pNode->colInfo.n == 0)) { + int32_t type = pItem->pNode->type; + if (type == SQL_NODE_SQLFUNCTION) { + pItem->pNode->functionId = isValidFunction(pItem->pNode->operand.z, pItem->pNode->operand.n); + if (pItem->pNode->functionId < 0) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5); } - // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2 - if (addProjectionExprAndResultField(pCmd, pQueryInfo, pItem) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_SQL; - } - } else if (pItem->pNode->nSQLOptr >= TK_COUNT && pItem->pNode->nSQLOptr <= TK_TBID) { // sql function in selection clause, append sql function info in pSqlCmd structure sequentially if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, pItem, true) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } - - } else if (pItem->pNode->nSQLOptr >= TK_PLUS && pItem->pNode->nSQLOptr <= TK_REM) { + } else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) { + // use the dynamic array list to decide if the function is valid or not + // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2 + if (addProjectionExprAndResultField(pCmd, pQueryInfo, pItem) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_SQL; + } + } else if (type == SQL_NODE_EXPR) { int32_t code = handleArithmeticExpr(pCmd, clauseIndex, i, pItem); if (code != TSDB_CODE_SUCCESS) { return code; @@ -1600,7 +1600,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel // there is only one user-defined column in the final result field, add the timestamp column. size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList); - if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo)) { + if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) { addPrimaryTsColIntoResult(pQueryInfo); } @@ -1727,7 +1727,7 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t const char* msg1 = "tag for normal table query is not allowed"; int32_t startPos = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); - int32_t optr = pItem->pNode->nSQLOptr; + int32_t optr = pItem->pNode->tokenId; if (optr == TK_ALL) { // project on all fields TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY); @@ -1757,13 +1757,13 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t index.columnIndex = (pQueryInfo->udColumnId--); index.tableIndex = 0; - SSchema colSchema = tGetUserSpecifiedColumnSchema(&pItem->pNode->val, &pItem->pNode->token, pItem->aliasName); + SSchema colSchema = tGetUserSpecifiedColumnSchema(&pItem->pNode->value, &pItem->pNode->token, pItem->aliasName); SSqlExpr* pExpr = tscAddFuncInSelectClause(pQueryInfo, startPos, TSDB_FUNC_PRJ, &index, &colSchema, TSDB_COL_UDC); // NOTE: the first parameter is reserved for the tag column id during join query process. pExpr->numOfParams = 2; - tVariantAssign(&pExpr->param[1], &pItem->pNode->val); + tVariantAssign(&pExpr->param[1], &pItem->pNode->value); } else if (optr == TK_ID) { SColumnIndex index = COLUMN_INDEX_INITIALIZER; @@ -1872,19 +1872,21 @@ void setResultColName(char* name, tSqlExprItem* pItem, int32_t functionId, SStrT } } +static void updateLastQueryInfoForGroupby(SQueryInfo* pQueryInfo, STableMeta* pTableMeta, int32_t functionId, int32_t index) { + if (functionId != TSDB_FUNC_LAST) { // todo refactor + return; + } -void setLastOrderForGoupBy(SQueryInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo) { // todo refactor SSqlGroupbyExpr* pGroupBy = &pQueryInfo->groupbyExpr; if (pGroupBy->numOfGroupCols > 0) { - size_t idx = taosArrayGetSize(pQueryInfo->exprList); for(int32_t k = 0; k < pGroupBy->numOfGroupCols; ++k) { SColIndex* pIndex = taosArrayGet(pGroupBy->columnInfo, k); - if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { // group by normal columns - SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, idx - 1); + if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < tscGetNumOfColumns(pTableMeta)) { // group by normal columns + SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, index); pExpr->numOfParams = 1; pExpr->param->i64 = TSDB_ORDER_ASC; - break; + return; } } } @@ -1892,7 +1894,7 @@ void setLastOrderForGoupBy(SQueryInfo* pQueryInfo, STableMetaInfo* pTableMetaInf int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult) { STableMetaInfo* pTableMetaInfo = NULL; - int32_t optr = pItem->pNode->nSQLOptr; + int32_t functionId = pItem->pNode->functionId; const char* msg1 = "not support column types"; const char* msg2 = "invalid parameters"; @@ -1902,28 +1904,22 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col const char* msg6 = "function applied to tags not allowed"; const char* msg7 = "normal table can not apply this function"; const char* msg8 = "multi-columns selection does not support alias column name"; - const char* msg9 = "invalid function"; const char* msg10 = "diff can no be applied to unsigned numeric type"; - switch (optr) { - case TK_COUNT: { + switch (functionId) { + case TSDB_FUNC_COUNT: { /* more than one parameter for count() function */ if (pItem->pNode->pParam != NULL && pItem->pNode->pParam->nExpr != 1) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } - int16_t functionID = 0; - if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_SQL; - } - SSqlExpr* pExpr = NULL; SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (pItem->pNode->pParam != NULL) { tSqlExprItem* pParamElem = &pItem->pNode->pParam->a[0]; SStrToken* pToken = &pParamElem->pNode->colInfo; - int16_t sqlOptr = pParamElem->pNode->nSQLOptr; + int16_t sqlOptr = pParamElem->pNode->tokenId; if ((pToken->z == NULL || pToken->n == 0) && (TK_INTEGER != sqlOptr)) /*select count(1) from table*/ { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); @@ -1939,11 +1935,11 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX}; int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false); + pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false); } else if (sqlOptr == TK_INTEGER) { // select count(1) from table1 char buf[8] = {0}; int64_t val = -1; - tVariant* pVariant = &pParamElem->pNode->val; + tVariant* pVariant = &pParamElem->pNode->value; if (pVariant->nType == TSDB_DATA_TYPE_BIGINT) { tVariantDump(pVariant, buf, TSDB_DATA_TYPE_BIGINT, true); val = GET_INT64_VAL(buf); @@ -1951,7 +1947,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col if (val == 1) { index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX}; int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false); + pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false); } else { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } @@ -1971,12 +1967,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, isTag); + pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, isTag); } } else { // count(*) is equalled to count(primary_timestamp_key) index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX}; int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false); + pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false); } pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); @@ -2001,29 +1997,29 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return TSDB_CODE_SUCCESS; } - case TK_SUM: - case TK_AVG: - case TK_RATE: - case TK_IRATE: - case TK_SUM_RATE: - case TK_SUM_IRATE: - case TK_AVG_RATE: - case TK_AVG_IRATE: - case TK_TWA: - case TK_MIN: - case TK_MAX: - case TK_DIFF: - case TK_STDDEV: - case TK_LEASTSQUARES: { + case TSDB_FUNC_SUM: + case TSDB_FUNC_AVG: + case TSDB_FUNC_RATE: + case TSDB_FUNC_IRATE: + case TSDB_FUNC_SUM_RATE: + case TSDB_FUNC_SUM_IRATE: + case TSDB_FUNC_AVG_RATE: + case TSDB_FUNC_AVG_IRATE: + case TSDB_FUNC_TWA: + case TSDB_FUNC_MIN: + case TSDB_FUNC_MAX: + case TSDB_FUNC_DIFF: + case TSDB_FUNC_STDDEV: + case TSDB_FUNC_LEASTSQR: { // 1. valid the number of parameters - if (pItem->pNode->pParam == NULL || (optr != TK_LEASTSQUARES && pItem->pNode->pParam->nExpr != 1) || - (optr == TK_LEASTSQUARES && pItem->pNode->pParam->nExpr != 3)) { + if (pItem->pNode->pParam == NULL || (functionId != TSDB_FUNC_LEASTSQR && pItem->pNode->pParam->nExpr != 1) || + (functionId == TSDB_FUNC_LEASTSQR && pItem->pNode->pParam->nExpr != 3)) { /* no parameters or more than one parameter for function */ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[0]); - if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) { + if (pParamElem->pNode->tokenId != TK_ALL && pParamElem->pNode->tokenId != TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -2043,7 +2039,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col if (!IS_NUMERIC_TYPE(colType)) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } else if (IS_UNSIGNED_NUMERIC_TYPE(colType) && optr == TK_DIFF) { + } else if (IS_UNSIGNED_NUMERIC_TYPE(colType) && functionId == TSDB_FUNC_DIFF) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg10); } @@ -2051,18 +2047,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col int16_t resultSize = 0; int32_t intermediateResSize = 0; - int16_t functionID = 0; - if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_SQL; - } - - if (getResultDataInfo(pSchema->type, pSchema->bytes, functionID, 0, &resultType, &resultSize, + if (getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize, &intermediateResSize, 0, false) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } // set the first column ts for diff query - if (optr == TK_DIFF) { + if (functionId == TSDB_FUNC_DIFF) { colIndex += 1; SColumnIndex indexTS = {.tableIndex = index.tableIndex, .columnIndex = 0}; SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &indexTS, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, @@ -2077,19 +2068,19 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6); } - SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false); + SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false); - if (optr == TK_LEASTSQUARES) { + if (functionId == TSDB_FUNC_LEASTSQR) { /* set the leastsquares parameters */ char val[8] = {0}; - if (tVariantDump(&pParamElem[1].pNode->val, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) { + if (tVariantDump(&pParamElem[1].pNode->value, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) { return TSDB_CODE_TSC_INVALID_SQL; } addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, DOUBLE_BYTES); memset(val, 0, tListLen(val)); - if (tVariantDump(&pParamElem[2].pNode->val, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) { + if (tVariantDump(&pParamElem[2].pNode->value, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -2115,21 +2106,16 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col tscInsertPrimaryTsSourceColumn(pQueryInfo, &index); return TSDB_CODE_SUCCESS; } - case TK_FIRST: - case TK_LAST: - case TK_SPREAD: - case TK_LAST_ROW: - case TK_INTERP: { + case TSDB_FUNC_FIRST: + case TSDB_FUNC_LAST: + case TSDB_FUNC_SPREAD: + case TSDB_FUNC_LAST_ROW: + case TSDB_FUNC_INTERP: { bool requireAllFields = (pItem->pNode->pParam == NULL); - int16_t functionID = 0; - if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9); - } - // NOTE: has time range condition or normal column filter condition, the last_row query will be transferred to last query - SConvertFunc cvtFunc = {.originFuncId = functionID, .execFuncId = functionID}; - if (functionID == TSDB_FUNC_LAST_ROW && ((!TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER)) || (hasNormalColumnFilter(pQueryInfo)))) { + SConvertFunc cvtFunc = {.originFuncId = functionId, .execFuncId = functionId}; + if (functionId == TSDB_FUNC_LAST_ROW && ((!TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER)) || (hasNormalColumnFilter(pQueryInfo)))) { cvtFunc.execFuncId = TSDB_FUNC_LAST; } @@ -2145,13 +2131,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col /* in first/last function, multiple columns can be add to resultset */ for (int32_t i = 0; i < pItem->pNode->pParam->nExpr; ++i) { tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[i]); - if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) { + if (pParamElem->pNode->tokenId != TK_ALL && pParamElem->pNode->tokenId != TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (pParamElem->pNode->nSQLOptr == TK_ALL) { // select table.* + if (pParamElem->pNode->tokenId == TK_ALL) { // select table.* SStrToken tmpToken = pParamElem->pNode->colInfo; if (getTableIndexByName(&tmpToken, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { @@ -2171,9 +2157,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return TSDB_CODE_TSC_INVALID_SQL; } - if (optr == TK_LAST) { - setLastOrderForGoupBy(pQueryInfo, pTableMetaInfo); - } + updateLastQueryInfoForGroupby(pQueryInfo, pTableMetaInfo->pTableMeta, functionId, colIndex - 1); } } else { @@ -2189,19 +2173,16 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } char name[TSDB_COL_NAME_LEN] = {0}; - SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); bool multiColOutput = pItem->pNode->pParam->nExpr > 1; setResultColName(name, pItem, cvtFunc.originFuncId, &pParamElem->pNode->colInfo, multiColOutput); - if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex++, &index, finalResult) != 0) { + if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex + i, &index, finalResult) != 0) { return TSDB_CODE_TSC_INVALID_SQL; } - if (optr == TK_LAST) { - setLastOrderForGoupBy(pQueryInfo, pTableMetaInfo); - } + updateLastQueryInfoForGroupby(pQueryInfo, pTableMetaInfo->pTableMeta, functionId, colIndex + i); } } @@ -2229,24 +2210,21 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return TSDB_CODE_TSC_INVALID_SQL; } + updateLastQueryInfoForGroupby(pQueryInfo, pTableMetaInfo->pTableMeta, functionId, colIndex); colIndex++; - - if (optr == TK_LAST) { - setLastOrderForGoupBy(pQueryInfo, pTableMetaInfo); - } } numOfFields += tscGetNumOfColumns(pTableMetaInfo->pTableMeta); } - return TSDB_CODE_SUCCESS; } } - case TK_TOP: - case TK_BOTTOM: - case TK_PERCENTILE: - case TK_APERCENTILE: { + + case TSDB_FUNC_TOP: + case TSDB_FUNC_BOTTOM: + case TSDB_FUNC_PERCT: + case TSDB_FUNC_APERCT: { // 1. valid the number of parameters if (pItem->pNode->pParam == NULL || pItem->pNode->pParam->nExpr != 2) { /* no parameters or more than one parameter for function */ @@ -2254,7 +2232,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[0]); - if (pParamElem->pNode->nSQLOptr != TK_ID) { + if (pParamElem->pNode->tokenId != TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -2282,11 +2260,11 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } // 3. valid the parameters - if (pParamElem[1].pNode->nSQLOptr == TK_ID) { + if (pParamElem[1].pNode->tokenId == TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } - tVariant* pVariant = &pParamElem[1].pNode->val; + tVariant* pVariant = &pParamElem[1].pNode->value; int8_t resultType = pSchema[index.columnIndex].type; int16_t resultSize = pSchema[index.columnIndex].bytes; @@ -2294,7 +2272,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col char val[8] = {0}; SSqlExpr* pExpr = NULL; - if (optr == TK_PERCENTILE || optr == TK_APERCENTILE) { + if (functionId == TSDB_FUNC_PERCT || functionId == TSDB_FUNC_APERCT) { tVariantDump(pVariant, val, TSDB_DATA_TYPE_DOUBLE, true); double dp = GET_DOUBLE_VAL(val); @@ -2310,10 +2288,6 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col * for dp = 0, it is actually min, * for dp = 100, it is max, */ - int16_t functionId = 0; - if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_SQL; - } tscInsertPrimaryTsSourceColumn(pQueryInfo, &index); colIndex += 1; // the first column is ts @@ -2327,11 +2301,6 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5); } - int16_t functionId = 0; - if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_SQL; - } - // todo REFACTOR // set the first column ts for top/bottom query SColumnIndex index1 = {0, PRIMARYKEY_TIMESTAMP_COL_INDEX}; @@ -2365,7 +2334,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return TSDB_CODE_SUCCESS; }; - case TK_TBID: { + case TSDB_FUNC_TID_TAG: { pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7); @@ -2433,7 +2402,31 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return TSDB_CODE_SUCCESS; } - + case TSDB_FUNC_BLKINFO: { + // no parameters or more than one parameter for function + if (pItem->pNode->pParam != NULL && pItem->pNode->pParam->nExpr != 0) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); + } + + SColumnIndex index = {.tableIndex = 0, .columnIndex = TSDB_BLOCK_DIST_COLUMN_INDEX,}; + pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); + + SSchema s = {.name = "block_dist", .type = TSDB_DATA_TYPE_BINARY}; + int32_t inter = 0; + int16_t resType = 0; + int16_t bytes = 0; + getResultDataInfo(TSDB_DATA_TYPE_INT, 4, TSDB_FUNC_BLKINFO, 0, &resType, &bytes, &inter, 0, 0); + + s.bytes = bytes; + s.type = (uint8_t)resType; + SSqlExpr* pExpr = tscAddFuncInSelectClause(pQueryInfo, 0, TSDB_FUNC_BLKINFO, &index, &s, TSDB_COL_TAG); + pExpr->numOfParams = 1; + pExpr->param[0].i64 = pTableMetaInfo->pTableMeta->tableInfo.rowSize; + pExpr->param[0].nType = TSDB_DATA_TYPE_BIGINT; + + return TSDB_CODE_SUCCESS; + } + default: return TSDB_CODE_TSC_INVALID_SQL; } @@ -2458,8 +2451,8 @@ void getColumnName(tSqlExprItem* pItem, char* resultFieldName, int32_t nameLengt if (pItem->aliasName != NULL) { strncpy(resultFieldName, pItem->aliasName, nameLength); } else { - int32_t len = ((int32_t)pItem->pNode->operand.n < nameLength) ? (int32_t)pItem->pNode->operand.n : nameLength; - strncpy(resultFieldName, pItem->pNode->operand.z, len); + int32_t len = ((int32_t)pItem->pNode->token.n < nameLength) ? (int32_t)pItem->pNode->token.n : nameLength; + strncpy(resultFieldName, pItem->pNode->token.z, len); } } @@ -2599,87 +2592,6 @@ int32_t getColumnIndexByName(SSqlCmd* pCmd, const SStrToken* pToken, SQueryInfo* return doGetColumnIndexByName(pCmd, &tmpToken, pQueryInfo, pIndex); } -int32_t convertFunctionId(int32_t optr, int16_t* functionId) { - switch (optr) { - case TK_COUNT: - *functionId = TSDB_FUNC_COUNT; - break; - case TK_SUM: - *functionId = TSDB_FUNC_SUM; - break; - case TK_AVG: - *functionId = TSDB_FUNC_AVG; - break; - case TK_RATE: - *functionId = TSDB_FUNC_RATE; - break; - case TK_IRATE: - *functionId = TSDB_FUNC_IRATE; - break; - case TK_SUM_RATE: - *functionId = TSDB_FUNC_SUM_RATE; - break; - case TK_SUM_IRATE: - *functionId = TSDB_FUNC_SUM_IRATE; - break; - case TK_AVG_RATE: - *functionId = TSDB_FUNC_AVG_RATE; - break; - case TK_AVG_IRATE: - *functionId = TSDB_FUNC_AVG_IRATE; - break; - case TK_MIN: - *functionId = TSDB_FUNC_MIN; - break; - case TK_MAX: - *functionId = TSDB_FUNC_MAX; - break; - case TK_STDDEV: - *functionId = TSDB_FUNC_STDDEV; - break; - case TK_PERCENTILE: - *functionId = TSDB_FUNC_PERCT; - break; - case TK_APERCENTILE: - *functionId = TSDB_FUNC_APERCT; - break; - case TK_FIRST: - *functionId = TSDB_FUNC_FIRST; - break; - case TK_LAST: - *functionId = TSDB_FUNC_LAST; - break; - case TK_LEASTSQUARES: - *functionId = TSDB_FUNC_LEASTSQR; - break; - case TK_TOP: - *functionId = TSDB_FUNC_TOP; - break; - case TK_BOTTOM: - *functionId = TSDB_FUNC_BOTTOM; - break; - case TK_DIFF: - *functionId = TSDB_FUNC_DIFF; - break; - case TK_SPREAD: - *functionId = TSDB_FUNC_SPREAD; - break; - case TK_TWA: - *functionId = TSDB_FUNC_TWA; - break; - case TK_INTERP: - *functionId = TSDB_FUNC_INTERP; - break; - case TK_LAST_ROW: - *functionId = TSDB_FUNC_LAST_ROW; - break; - default: - return -1; - } - - return TSDB_CODE_SUCCESS; -} - int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { SSqlCmd* pCmd = &pSql->cmd; STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0); @@ -3113,39 +3025,39 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, colType = TSDB_DATA_TYPE_BIGINT; } else if (colType == TSDB_DATA_TYPE_FLOAT || colType == TSDB_DATA_TYPE_DOUBLE) { colType = TSDB_DATA_TYPE_DOUBLE; - } else if ((colType == TSDB_DATA_TYPE_TIMESTAMP) && (TSDB_DATA_TYPE_BINARY == pRight->val.nType)) { - int retVal = setColumnFilterInfoForTimestamp(pCmd, pQueryInfo, &pRight->val); + } else if ((colType == TSDB_DATA_TYPE_TIMESTAMP) && (TSDB_DATA_TYPE_BINARY == pRight->value.nType)) { + int retVal = setColumnFilterInfoForTimestamp(pCmd, pQueryInfo, &pRight->value); if (TSDB_CODE_SUCCESS != retVal) { return retVal; } } int32_t retVal = TSDB_CODE_SUCCESS; - if (pExpr->nSQLOptr == TK_LE || pExpr->nSQLOptr == TK_LT) { - retVal = tVariantDump(&pRight->val, (char*)&pColumnFilter->upperBndd, colType, false); + if (pExpr->tokenId == TK_LE || pExpr->tokenId == TK_LT) { + 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 (colType == TSDB_DATA_TYPE_BINARY) { - pColumnFilter->pz = (int64_t)calloc(1, pRight->val.nLen + TSDB_NCHAR_SIZE); - pColumnFilter->len = pRight->val.nLen; - retVal = tVariantDump(&pRight->val, (char*)pColumnFilter->pz, colType, false); + pColumnFilter->pz = (int64_t)calloc(1, pRight->value.nLen + TSDB_NCHAR_SIZE); + pColumnFilter->len = pRight->value.nLen; + retVal = tVariantDump(&pRight->value, (char*)pColumnFilter->pz, colType, false); } else if (colType == TSDB_DATA_TYPE_NCHAR) { - // pRight->val.nLen + 1 is larger than the actual nchar string length - pColumnFilter->pz = (int64_t)calloc(1, (pRight->val.nLen + 1) * TSDB_NCHAR_SIZE); - retVal = tVariantDump(&pRight->val, (char*)pColumnFilter->pz, colType, false); + // pRight->value.nLen + 1 is larger than the actual nchar string length + pColumnFilter->pz = (int64_t)calloc(1, (pRight->value.nLen + 1) * TSDB_NCHAR_SIZE); + retVal = tVariantDump(&pRight->value, (char*)pColumnFilter->pz, colType, false); size_t len = twcslen((wchar_t*)pColumnFilter->pz); pColumnFilter->len = len * TSDB_NCHAR_SIZE; } else { - retVal = tVariantDump(&pRight->val, (char*)&pColumnFilter->lowerBndd, colType, false); + retVal = tVariantDump(&pRight->value, (char*)&pColumnFilter->lowerBndd, colType, false); } if (retVal != TSDB_CODE_SUCCESS) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg); } - switch (pExpr->nSQLOptr) { + switch (pExpr->tokenId) { case TK_LE: pColumnFilter->upperRelOptr = TSDB_RELATION_LESS_EQUAL; break; @@ -3198,14 +3110,14 @@ typedef struct SCondExpr { static int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t timePrecision); static int32_t tSQLExprNodeToString(tSQLExpr* pExpr, char** str) { - if (pExpr->nSQLOptr == TK_ID) { // column name + if (pExpr->tokenId == TK_ID) { // column name strncpy(*str, pExpr->colInfo.z, pExpr->colInfo.n); *str += pExpr->colInfo.n; - } else if (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_STRING) { // value - *str += tVariantToString(&pExpr->val, *str); + } else if (pExpr->tokenId >= TK_BOOL && pExpr->tokenId <= TK_STRING) { // value + *str += tVariantToString(&pExpr->value, *str); - } else if (pExpr->nSQLOptr >= TK_COUNT && pExpr->nSQLOptr <= TK_AVG_IRATE) { + } else if (pExpr->tokenId >= TSDB_FUNC_COUNT && pExpr->tokenId <= TSDB_FUNC_BLKINFO) { /* * arithmetic expression of aggregation, such as count(ts) + count(ts) *2 */ @@ -3218,10 +3130,10 @@ static int32_t tSQLExprNodeToString(tSQLExpr* pExpr, char** str) { return TSDB_CODE_SUCCESS; } -// pExpr->nSQLOptr == 0 while handling "is null" query +// pExpr->tokenId == 0 while handling "is null" query static bool isExprLeafNode(tSQLExpr* pExpr) { return (pExpr->pRight == NULL && pExpr->pLeft == NULL) && - (pExpr->nSQLOptr == 0 || pExpr->nSQLOptr == TK_ID || (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_NCHAR) || pExpr->nSQLOptr == TK_SET); + (pExpr->tokenId == 0 || pExpr->tokenId == TK_ID || (pExpr->tokenId >= TK_BOOL && pExpr->tokenId <= TK_NCHAR) || pExpr->tokenId == TK_SET); } static bool isExprDirectParentOfLeafNode(tSQLExpr* pExpr) { @@ -3263,7 +3175,7 @@ static int32_t optrToString(tSQLExpr* pExpr, char** exprString) { const char* ne = "<>"; const char* likeOptr = "LIKE"; - switch (pExpr->nSQLOptr) { + switch (pExpr->tokenId) { case TK_LE: { *(int16_t*)(*exprString) = *(int16_t*)le; *exprString += 1; @@ -3330,13 +3242,13 @@ static int32_t tablenameListToString(tSQLExpr* pExpr, SStringBuilder* sb) { for (int32_t i = 0; i < pList->nExpr; ++i) { tSQLExpr* pSub = pList->a[i].pNode; - taosStringBuilderAppendStringLen(sb, pSub->val.pz, pSub->val.nLen); + taosStringBuilderAppendStringLen(sb, pSub->value.pz, pSub->value.nLen); if (i < pList->nExpr - 1) { taosStringBuilderAppendString(sb, TBNAME_LIST_SEP); } - if (pSub->val.nLen <= 0 || !tscValidateTableNameLength(pSub->val.nLen)) { + if (pSub->value.nLen <= 0 || !tscValidateTableNameLength(pSub->value.nLen)) { return TSDB_CODE_TSC_INVALID_SQL; } } @@ -3346,7 +3258,7 @@ static int32_t tablenameListToString(tSQLExpr* pExpr, SStringBuilder* sb) { static int32_t tablenameCondToString(tSQLExpr* pExpr, SStringBuilder* sb) { taosStringBuilderAppendStringLen(sb, QUERY_COND_REL_PREFIX_LIKE, QUERY_COND_REL_PREFIX_LIKE_LEN); - taosStringBuilderAppendString(sb, pExpr->val.pz); + taosStringBuilderAppendString(sb, pExpr->value.pz); return TSDB_CODE_SUCCESS; } @@ -3400,21 +3312,21 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC ((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0); if (pColFilter->filterstr) { - if (pExpr->nSQLOptr != TK_EQ - && pExpr->nSQLOptr != TK_NE - && pExpr->nSQLOptr != TK_ISNULL - && pExpr->nSQLOptr != TK_NOTNULL - && pExpr->nSQLOptr != TK_LIKE + if (pExpr->tokenId != TK_EQ + && pExpr->tokenId != TK_NE + && pExpr->tokenId != TK_ISNULL + && pExpr->tokenId != TK_NOTNULL + && pExpr->tokenId != TK_LIKE ) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } } else { - if (pExpr->nSQLOptr == TK_LIKE) { + if (pExpr->tokenId == TK_LIKE) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } if (pSchema->type == TSDB_DATA_TYPE_BOOL) { - if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) { + if (pExpr->tokenId != TK_EQ && pExpr->tokenId != TK_NE) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } } @@ -3425,13 +3337,13 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC } static void relToString(tSQLExpr* pExpr, char** str) { - assert(pExpr->nSQLOptr == TK_AND || pExpr->nSQLOptr == TK_OR); + assert(pExpr->tokenId == TK_AND || pExpr->tokenId == TK_OR); const char* or = "OR"; const char*and = "AND"; // if (pQueryInfo->tagCond.relType == TSQL_STABLE_QTYPE_COND) { - if (pExpr->nSQLOptr == TK_AND) { + if (pExpr->tokenId == TK_AND) { strcpy(*str, and); *str += strlen(and); } else { @@ -3485,10 +3397,10 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* int32_t ret = TSDB_CODE_SUCCESS; - if (pTableCond->nSQLOptr == TK_IN) { + if (pTableCond->tokenId == TK_IN) { ret = tablenameListToString(pRight, sb); - } else if (pTableCond->nSQLOptr == TK_LIKE) { - if (pRight->nSQLOptr != TK_STRING) { + } else if (pTableCond->tokenId == TK_LIKE) { + if (pRight->tokenId != TK_STRING) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } @@ -3508,12 +3420,12 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQ } if (!isExprDirectParentOfLeafNode(pExpr)) { // internal node - int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->nSQLOptr); + int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; } - return getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->nSQLOptr); + return getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId); } else { // handle leaf node SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(pCmd, &pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { @@ -3583,8 +3495,8 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* } static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, - int32_t* type, uint64_t* uid) { - if (pExpr->nSQLOptr == TK_ID) { + int32_t* type, uint64_t* uid) { + if (pExpr->type == SQL_NODE_TABLE_COLUMN) { if (*type == NON_ARITHMEIC_EXPR) { *type = NORMAL_ARITHMETIC; } else if (*type == AGG_ARIGHTMEIC) { @@ -3606,9 +3518,9 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer } pList->ids[pList->num++] = index; - } else if (pExpr->nSQLOptr == TK_FLOAT && (isnan(pExpr->val.dKey) || isinf(pExpr->val.dKey))) { + } else if (pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.dKey) || isinf(pExpr->value.dKey))) { return TSDB_CODE_TSC_INVALID_SQL; - } else if (pExpr->nSQLOptr >= TK_COUNT && pExpr->nSQLOptr <= TK_AVG_IRATE) { + } else if (pExpr->type == SQL_NODE_SQLFUNCTION) { if (*type == NON_ARITHMEIC_EXPR) { *type = AGG_ARIGHTMEIC; } else if (*type == NORMAL_ARITHMETIC) { @@ -3621,6 +3533,11 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer // sql function list in selection clause. // Append the sqlExpr into exprList of pQueryInfo structure sequentially + pExpr->functionId = isValidFunction(pExpr->operand.z, pExpr->operand.n); + if (pExpr->functionId < 0) { + return TSDB_CODE_TSC_INVALID_SQL; + } + if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, false) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -3662,7 +3579,7 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI uint64_t uidLeft = 0; uint64_t uidRight = 0; - if (pLeft->nSQLOptr >= TK_PLUS && pLeft->nSQLOptr <= TK_REM) { + if (pLeft->type == SQL_NODE_EXPR) { int32_t ret = validateArithmeticSQLExpr(pCmd, pLeft, pQueryInfo, pList, type); if (ret != TSDB_CODE_SUCCESS) { return ret; @@ -3675,7 +3592,7 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI } tSQLExpr* pRight = pExpr->pRight; - if (pRight->nSQLOptr >= TK_PLUS && pRight->nSQLOptr <= TK_REM) { + if (pRight->type == SQL_NODE_EXPR) { int32_t ret = validateArithmeticSQLExpr(pCmd, pRight, pQueryInfo, pList, type); if (ret != TSDB_CODE_SUCCESS) { return ret; @@ -3708,22 +3625,15 @@ static bool isValidExpr(tSQLExpr* pLeft, tSQLExpr* pRight, int32_t optr) { * * However, columnA < 4+12 is valid */ - if (pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE) { + if (pLeft->type == SQL_NODE_SQLFUNCTION) { return false; } if (pRight == NULL) { return true; } - - if (pRight->nSQLOptr >= TK_COUNT && pRight->nSQLOptr <= TK_AVG_IRATE) { - return false; - } - if (pLeft->nSQLOptr >= TK_BOOL - && pLeft->nSQLOptr <= TK_BINARY - && pRight->nSQLOptr >= TK_BOOL - && pRight->nSQLOptr <= TK_BINARY) { + if (pLeft->tokenId >= TK_BOOL && pLeft->tokenId <= TK_BINARY && pRight->tokenId >= TK_BOOL && pRight->tokenId <= TK_BINARY) { return false; } @@ -3734,8 +3644,8 @@ static void exchangeExpr(tSQLExpr* pExpr) { tSQLExpr* pLeft = pExpr->pLeft; tSQLExpr* pRight = pExpr->pRight; - if (pRight->nSQLOptr == TK_ID && (pLeft->nSQLOptr == TK_INTEGER || pLeft->nSQLOptr == TK_FLOAT || - pLeft->nSQLOptr == TK_STRING || pLeft->nSQLOptr == TK_BOOL)) { + if (pRight->tokenId == TK_ID && (pLeft->tokenId == TK_INTEGER || pLeft->tokenId == TK_FLOAT || + pLeft->tokenId == TK_STRING || pLeft->tokenId == TK_BOOL)) { /* * exchange value of the left handside and the value of the right-handside * to make sure that the value of filter expression always locates in @@ -3743,7 +3653,7 @@ static void exchangeExpr(tSQLExpr* pExpr) { * the column-id is at the left handside. */ uint32_t optr = 0; - switch (pExpr->nSQLOptr) { + switch (pExpr->tokenId) { case TK_LE: optr = TK_GE; break; @@ -3757,10 +3667,10 @@ static void exchangeExpr(tSQLExpr* pExpr) { optr = TK_LE; break; default: - optr = pExpr->nSQLOptr; + optr = pExpr->tokenId; } - pExpr->nSQLOptr = optr; + pExpr->tokenId = optr; SWAP(pExpr->pLeft, pExpr->pRight, void*); } } @@ -3774,11 +3684,11 @@ static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr tSQLExpr* pRight = pExpr->pRight; - if (pRight->nSQLOptr != TK_ID) { + if (pRight->tokenId != TK_ID) { return true; } - if (pExpr->nSQLOptr != TK_EQ) { + if (pExpr->tokenId != TK_EQ) { invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); return false; } @@ -3820,7 +3730,7 @@ static bool validTableNameOptr(tSQLExpr* pExpr) { const char nameFilterOptr[] = {TK_IN, TK_LIKE}; for (int32_t i = 0; i < tListLen(nameFilterOptr); ++i) { - if (pExpr->nSQLOptr == nameFilterOptr[i]) { + if (pExpr->tokenId == nameFilterOptr[i]) { return true; } } @@ -3874,7 +3784,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL } // set join query condition - if (pRight->nSQLOptr == TK_ID) { // no need to keep the timestamp join condition + if (pRight->tokenId == TK_ID) { // no need to keep the timestamp join condition TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY); pCondExpr->tsJoin = true; @@ -3896,8 +3806,8 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL } // check for like expression - if ((*pExpr)->nSQLOptr == TK_LIKE) { - if (pRight->val.nLen > TSDB_PATTERN_STRING_MAX_LEN) { + if ((*pExpr)->tokenId == TK_LIKE) { + if (pRight->value.nLen > TSDB_PATTERN_STRING_MAX_LEN) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8); } @@ -3930,7 +3840,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL *type = TSQL_EXPR_TBNAME; *pExpr = NULL; } else { - if (pRight != NULL && pRight->nSQLOptr == TK_ID) { // join on tag columns for stable query + if (pRight != NULL && pRight->tokenId == TK_ID) { // join on tag columns for stable query if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -3954,7 +3864,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL } else { // query on other columns *type = TSQL_EXPR_COLUMN; - if (pRight->nSQLOptr == TK_ID) { // other column cannot be served as the join column + if (pRight->tokenId == TK_ID) { // other column cannot be served as the join column return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5); } @@ -3976,7 +3886,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr tSQLExpr* pLeft = (*pExpr)->pLeft; tSQLExpr* pRight = (*pExpr)->pRight; - if (!isValidExpr(pLeft, pRight, (*pExpr)->nSQLOptr)) { + if (!isValidExpr(pLeft, pRight, (*pExpr)->tokenId)) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -3984,12 +3894,12 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr int32_t rightType = -1; if (!isExprDirectParentOfLeafNode(*pExpr)) { - int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->nSQLOptr); + int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; } - ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->nSQLOptr); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; } @@ -3999,7 +3909,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr * expression is not valid for parent node, it must be TK_AND operator. */ if (leftType != rightType) { - if ((*pExpr)->nSQLOptr == TK_OR && (leftType + rightType != TSQL_EXPR_TBNAME + TSQL_EXPR_TAG)) { + if ((*pExpr)->tokenId == TK_OR && (leftType + rightType != TSQL_EXPR_TBNAME + TSQL_EXPR_TAG)) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } } @@ -4027,7 +3937,7 @@ static void doCompactQueryExpr(tSQLExpr** pExpr) { } if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight == NULL && - ((*pExpr)->nSQLOptr == TK_OR || (*pExpr)->nSQLOptr == TK_AND)) { + ((*pExpr)->tokenId == TK_OR || (*pExpr)->tokenId == TK_AND)) { tSqlExprNodeDestroy(*pExpr); *pExpr = NULL; @@ -4061,7 +3971,7 @@ static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo* (*pExpr) = NULL; } else { - *pOut = tSqlExprCreate(NULL, NULL, (*pExpr)->nSQLOptr); + *pOut = tSqlExprCreate(NULL, NULL, (*pExpr)->tokenId); doExtractExprForSTable(pCmd, &(*pExpr)->pLeft, pQueryInfo, &((*pOut)->pLeft), tableIndex); doExtractExprForSTable(pCmd, &(*pExpr)->pRight, pQueryInfo, &((*pOut)->pRight), tableIndex); @@ -4105,9 +4015,9 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, STagCond* pTagCond = &pQueryInfo->tagCond; pTagCond->tbnameCond.uid = pTableMetaInfo->pTableMeta->id.uid; - assert(pExpr->nSQLOptr == TK_LIKE || pExpr->nSQLOptr == TK_IN); + assert(pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_IN); - if (pExpr->nSQLOptr == TK_LIKE) { + if (pExpr->tokenId == TK_LIKE) { char* str = taosStringBuilderGetResult(sb, NULL); pQueryInfo->tagCond.tbnameCond.cond = strdup(str); pQueryInfo->tagCond.tbnameCond.len = (int32_t) strlen(str); @@ -4203,7 +4113,7 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLE } if (!isExprDirectParentOfLeafNode(pExpr)) { - if (pExpr->nSQLOptr == TK_OR) { + if (pExpr->tokenId == TK_OR) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } @@ -4222,7 +4132,7 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLE tSQLExpr* pRight = pExpr->pRight; STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; - if (getTimeRange(&win, pRight, pExpr->nSQLOptr, tinfo.precision) != TSDB_CODE_SUCCESS) { + if (getTimeRange(&win, pRight, pExpr->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0); } @@ -4366,7 +4276,7 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { retVal = tVariantDump(vVariant, tmp, schemaType, false); free(tmp); } else if (schemaType == TSDB_DATA_TYPE_NCHAR) { - // pRight->val.nLen + 1 is larger than the actual nchar string length + // pRight->value.nLen + 1 is larger than the actual nchar string length char *tmp = calloc(1, (vVariant->nLen + 1) * TSDB_NCHAR_SIZE); retVal = tVariantDump(vVariant, tmp, schemaType, false); free(tmp); @@ -4465,7 +4375,7 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql } int32_t type = 0; - if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->nSQLOptr)) != TSDB_CODE_SUCCESS) { + if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->tokenId)) != TSDB_CODE_SUCCESS) { return ret; } @@ -4522,7 +4432,7 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t timePrecision) { // this is join condition, do nothing - if (pRight->nSQLOptr == TK_ID) { + if (pRight->tokenId == TK_ID) { return TSDB_CODE_SUCCESS; } @@ -4530,42 +4440,42 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t * filter primary ts filter expression like: * where ts in ('2015-12-12 4:8:12') */ - if (pRight->nSQLOptr == TK_SET || optr == TK_IN) { + if (pRight->tokenId == TK_SET || optr == TK_IN) { return TSDB_CODE_TSC_INVALID_SQL; } int64_t val = 0; bool parsed = false; - if (pRight->val.nType == TSDB_DATA_TYPE_BINARY) { - pRight->val.nLen = strdequote(pRight->val.pz); + if (pRight->value.nType == TSDB_DATA_TYPE_BINARY) { + pRight->value.nLen = strdequote(pRight->value.pz); - char* seg = strnchr(pRight->val.pz, '-', pRight->val.nLen, false); + char* seg = strnchr(pRight->value.pz, '-', pRight->value.nLen, false); if (seg != NULL) { - if (taosParseTime(pRight->val.pz, &val, pRight->val.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) { + if (taosParseTime(pRight->value.pz, &val, pRight->value.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) { parsed = true; } else { return TSDB_CODE_TSC_INVALID_SQL; } } else { - SStrToken token = {.z = pRight->val.pz, .n = pRight->val.nLen, .type = TK_ID}; - int32_t len = tSQLGetToken(pRight->val.pz, &token.type); + SStrToken token = {.z = pRight->value.pz, .n = pRight->value.nLen, .type = TK_ID}; + int32_t len = tSQLGetToken(pRight->value.pz, &token.type); - if ((token.type != TK_INTEGER && token.type != TK_FLOAT) || len != pRight->val.nLen) { + if ((token.type != TK_INTEGER && token.type != TK_FLOAT) || len != pRight->value.nLen) { return TSDB_CODE_TSC_INVALID_SQL; } } - } else if (pRight->nSQLOptr == TK_INTEGER && timePrecision == TSDB_TIME_PRECISION_MILLI) { + } else if (pRight->tokenId == TK_INTEGER && timePrecision == TSDB_TIME_PRECISION_MILLI) { /* - * if the pRight->nSQLOptr == TK_INTEGER/TK_FLOAT, the value is adaptive, we + * if the pRight->tokenId == TK_INTEGER/TK_FLOAT, the value is adaptive, we * need the time precision in metermeta to transfer the value in MICROSECOND * * Additional check to avoid data overflow */ - if (pRight->val.i64 <= INT64_MAX / 1000) { - pRight->val.i64 *= 1000; + if (pRight->value.i64 <= INT64_MAX / 1000) { + pRight->value.i64 *= 1000; } - } else if (pRight->nSQLOptr == TK_FLOAT && timePrecision == TSDB_TIME_PRECISION_MILLI) { - pRight->val.dKey *= 1000; + } else if (pRight->tokenId == TK_FLOAT && timePrecision == TSDB_TIME_PRECISION_MILLI) { + pRight->value.dKey *= 1000; } if (!parsed) { @@ -4573,7 +4483,7 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t * failed to parse timestamp in regular formation, try next * it may be a epoch time in string format */ - tVariantDump(&pRight->val, (char*)&val, TSDB_DATA_TYPE_BIGINT, true); + tVariantDump(&pRight->value, (char*)&val, TSDB_DATA_TYPE_BIGINT, true); /* * transfer it into MICROSECOND format if it is a string, since for @@ -4581,7 +4491,7 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t * * additional check to avoid data overflow */ - if (pRight->nSQLOptr == TK_STRING && timePrecision == TSDB_TIME_PRECISION_MILLI) { + if (pRight->tokenId == TK_STRING && timePrecision == TSDB_TIME_PRECISION_MILLI) { if (val <= INT64_MAX / 1000) { val *= 1000; } @@ -5392,7 +5302,7 @@ int32_t validateLocalConfig(SMiscInfo* pOptions) { // reset log does not need value for (int32_t i = 0; i < 1; ++i) { SDNodeDynConfOption* pOption = &LOCAL_DYNAMIC_CFG_OPTIONS[i]; - if ((pOption->len == pOptionToken->n) && + if ((pOption->len == pOptionToken->n) && (strncasecmp(pOption->name, pOptionToken->z, pOptionToken->n) == 0)) { return TSDB_CODE_SUCCESS; } @@ -5407,7 +5317,7 @@ int32_t validateLocalConfig(SMiscInfo* pOptions) { for (int32_t i = 1; i < tListLen(LOCAL_DYNAMIC_CFG_OPTIONS); ++i) { SDNodeDynConfOption* pOption = &LOCAL_DYNAMIC_CFG_OPTIONS[i]; - if ((pOption->len == pOptionToken->n) + if ((pOption->len == pOptionToken->n) && (strncasecmp(pOption->name, pOptionToken->z, pOptionToken->n) == 0)) { return TSDB_CODE_SUCCESS; } @@ -6157,8 +6067,8 @@ int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ index = 2; } else { for (int32_t i = 0; i < tListLen(functionsInfo); ++i) { - if (strncasecmp(functionsInfo[i].name, pExpr->operand.z, functionsInfo[i].len) == 0 && - functionsInfo[i].len == pExpr->operand.n) { + if (strncasecmp(functionsInfo[i].name, pExpr->token.z, functionsInfo[i].len) == 0 && + functionsInfo[i].len == pExpr->token.n) { index = i; break; } @@ -6453,12 +6363,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { tVariantListItem* pItem = taosArrayGet(pValList, i); findColumnIndex = false; - + // todo speedup by using hash list for (int32_t t = 0; t < schemaSize; ++t) { if (strncmp(sToken->z, pTagSchema[t].name, sToken->n) == 0 && strlen(pTagSchema[t].name) == sToken->n) { SSchema* pSchema = &pTagSchema[t]; - + char tagVal[TSDB_MAX_TAGS_LEN]; if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { if (pItem->pVar.nLen > pSchema->bytes) { @@ -6466,9 +6376,9 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } } - + ret = tVariantDump(&(pItem->pVar), tagVal, pSchema->type, true); - + // check again after the convert since it may be converted from binary to nchar. if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { int16_t len = varDataTLen(tagVal); @@ -6477,12 +6387,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } } - + if (ret != TSDB_CODE_SUCCESS) { tdDestroyKVRowBuilder(&kvRowBuilder); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4); } - + tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal); findColumnIndex = true; @@ -6493,7 +6403,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { if (!findColumnIndex) { tdDestroyKVRowBuilder(&kvRowBuilder); return tscInvalidSQLErrMsg(pCmd->payload, "invalid tag name", sToken->z); - } + } } } else { if (schemaSize != valSize) { @@ -6504,7 +6414,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { for (int32_t i = 0; i < valSize; ++i) { SSchema* pSchema = &pTagSchema[i]; tVariantListItem* pItem = taosArrayGet(pValList, i); - + char tagVal[TSDB_MAX_TAGS_LEN]; if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { if (pItem->pVar.nLen > pSchema->bytes) { @@ -6512,9 +6422,9 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } } - + ret = tVariantDump(&(pItem->pVar), tagVal, pSchema->type, true); - + // check again after the convert since it may be converted from binary to nchar. if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { int16_t len = varDataTLen(tagVal); @@ -6523,12 +6433,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); } } - + if (ret != TSDB_CODE_SUCCESS) { tdDestroyKVRowBuilder(&kvRowBuilder); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4); } - + tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal); } } @@ -6953,25 +6863,25 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS } } - if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->nSQLOptr == 0) { + if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) { *pExpr = calloc(1, sizeof(tExprNode)); return TSDB_CODE_SUCCESS; } if (pSqlExpr->pLeft == NULL) { - if (pSqlExpr->nSQLOptr >= TK_BOOL && pSqlExpr->nSQLOptr <= TK_STRING) { + if (pSqlExpr->type == SQL_NODE_VALUE) { *pExpr = calloc(1, sizeof(tExprNode)); (*pExpr)->nodeType = TSQL_NODE_VALUE; (*pExpr)->pVal = calloc(1, sizeof(tVariant)); - tVariantAssign((*pExpr)->pVal, &pSqlExpr->val); + tVariantAssign((*pExpr)->pVal, &pSqlExpr->value); return TSDB_CODE_SUCCESS; - } else if (pSqlExpr->nSQLOptr >= TK_COUNT && pSqlExpr->nSQLOptr <= TK_AVG_IRATE) { + } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { // arithmetic expression on the results of aggregation functions *pExpr = calloc(1, sizeof(tExprNode)); (*pExpr)->nodeType = TSQL_NODE_COL; (*pExpr)->pSchema = calloc(1, sizeof(SSchema)); - strncpy((*pExpr)->pSchema->name, pSqlExpr->operand.z, pSqlExpr->operand.n); + strncpy((*pExpr)->pSchema->name, pSqlExpr->token.z, pSqlExpr->token.n); // set the input column data byte and type. size_t size = taosArrayGetSize(pQueryInfo->exprList); @@ -6991,7 +6901,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS break; } } - } else if (pSqlExpr->nSQLOptr == TK_ID) { // column name, normal column arithmetic expression + } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column arithmetic expression SColumnIndex index = COLUMN_INDEX_INITIALIZER; int32_t ret = getColumnIndexByName(pCmd, &pSqlExpr->colInfo, pQueryInfo, &index); if (ret != TSDB_CODE_SUCCESS) { @@ -7031,7 +6941,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS (*pExpr)->_node.pLeft = pLeft; (*pExpr)->_node.pRight = pRight; - SStrToken t = {.type = pSqlExpr->nSQLOptr}; + SStrToken t = {.type = pSqlExpr->tokenId}; (*pExpr)->_node.optr = convertOptr(&t); assert((*pExpr)->_node.optr != 0); diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 9e43ae674dfb4a1c845b7ca4db82b1cf6be4d0dd..81269d468648927f13320ca3dc38cb3fc784bb77 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -497,8 +497,6 @@ int tscProcessSql(SSqlObj *pSql) { return pSql->res.code; } } else if (pCmd->command >= TSDB_SQL_LOCAL) { - //pSql->epSet = tscMgmtEpSet; -// } else { // local handler return (*tscProcessMsgRsp[pCmd->command])(pSql); } @@ -705,7 +703,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { STableMeta * pTableMeta = pTableMetaInfo->pTableMeta; size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList); - if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo)) { + if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) { tscError("%p illegal value of numOfCols in query msg: %" PRIu64 ", table cols:%d", pSql, (uint64_t)numOfSrcCols, tscGetNumOfColumns(pTableMeta)); @@ -835,13 +833,31 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pSqlFuncExpr->colInfo.colIndex = htons(pExpr->colInfo.colIndex); pSqlFuncExpr->colInfo.flag = htons(pExpr->colInfo.flag); + if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) { + pSqlFuncExpr->colType = htons(pExpr->resType); + pSqlFuncExpr->colBytes = htons(pExpr->resBytes); + } else if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { + SSchema *s = tGetTbnameColumnSchema(); + + pSqlFuncExpr->colType = htons(s->type); + pSqlFuncExpr->colBytes = htons(s->bytes); + } else if (pExpr->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) { + SSchema s = tGetBlockDistColumnSchema(); + + pSqlFuncExpr->colType = htons(s.type); + pSqlFuncExpr->colBytes = htons(s.bytes); + } else { + SSchema* s = tscGetColumnSchemaById(pTableMeta, pExpr->colInfo.colId); + pSqlFuncExpr->colType = htons(s->type); + pSqlFuncExpr->colBytes = htons(s->bytes); + } + pSqlFuncExpr->functionId = htons(pExpr->functionId); pSqlFuncExpr->numOfParams = htons(pExpr->numOfParams); pSqlFuncExpr->resColId = htons(pExpr->resColId); pMsg += sizeof(SSqlFuncMsg); - for (int32_t j = 0; j < pExpr->numOfParams; ++j) { - // todo add log + for (int32_t j = 0; j < pExpr->numOfParams; ++j) { // todo add log pSqlFuncExpr->arg[j].argType = htons((uint16_t)pExpr->param[j].nType); pSqlFuncExpr->arg[j].argBytes = htons(pExpr->param[j].nLen); @@ -866,6 +882,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { for (int32_t i = 0; i < output; ++i) { SInternalField* pField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i); SSqlExpr *pExpr = pField->pSqlExpr; + + // this should be switched to projection query if (pExpr != NULL) { // the queried table has been removed and a new table with the same name has already been created already // return error msg @@ -879,33 +897,31 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { return TSDB_CODE_TSC_INVALID_SQL; } - pSqlFuncExpr1->colInfo.colId = htons(pExpr->colInfo.colId); - pSqlFuncExpr1->colInfo.colIndex = htons(pExpr->colInfo.colIndex); - pSqlFuncExpr1->colInfo.flag = htons(pExpr->colInfo.flag); - - pSqlFuncExpr1->functionId = htons(pExpr->functionId); - pSqlFuncExpr1->numOfParams = htons(pExpr->numOfParams); - pMsg += sizeof(SSqlFuncMsg); - - for (int32_t j = 0; j < pExpr->numOfParams; ++j) { - // todo add log - pSqlFuncExpr1->arg[j].argType = htons((uint16_t)pExpr->param[j].nType); - pSqlFuncExpr1->arg[j].argBytes = htons(pExpr->param[j].nLen); - - if (pExpr->param[j].nType == TSDB_DATA_TYPE_BINARY) { - memcpy(pMsg, pExpr->param[j].pz, pExpr->param[j].nLen); - pMsg += pExpr->param[j].nLen; - } else { - pSqlFuncExpr1->arg[j].argValue.i64 = htobe64(pExpr->param[j].i64); + pSqlFuncExpr1->numOfParams = 0; // no params for projection query + pSqlFuncExpr1->functionId = htons(TSDB_FUNC_PRJ); + pSqlFuncExpr1->colInfo.colId = htons(pExpr->resColId); + pSqlFuncExpr1->colInfo.flag = htons(TSDB_COL_NORMAL); + + bool assign = false; + for (int32_t f = 0; f < tscSqlExprNumOfExprs(pQueryInfo); ++f) { + SSqlExpr *pe = tscSqlExprGet(pQueryInfo, f); + if (pe == pExpr) { + pSqlFuncExpr1->colInfo.colIndex = htons(f); + pSqlFuncExpr1->colType = htons(pe->resType); + pSqlFuncExpr1->colBytes = htons(pe->resBytes); + assign = true; + break; } } + assert(assign); + pMsg += sizeof(SSqlFuncMsg); pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg; } else { assert(pField->pArithExprInfo != NULL); SExprInfo* pExprInfo = pField->pArithExprInfo; - pSqlFuncExpr1->colInfo.colId = htons(pExprInfo->base.colInfo.colId); + pSqlFuncExpr1->colInfo.colId = htons(pExprInfo->base.colInfo.colId); pSqlFuncExpr1->functionId = htons(pExprInfo->base.functionId); pSqlFuncExpr1->numOfParams = htons(pExprInfo->base.numOfParams); pMsg += sizeof(SSqlFuncMsg); diff --git a/src/client/src/tscSub.c b/src/client/src/tscSub.c index f3d7ef28c05fc3128622f8217341d52327d79ec0..32257f5a7c723d04ec0f8200c889a68d78cf7824 100644 --- a/src/client/src/tscSub.c +++ b/src/client/src/tscSub.c @@ -503,9 +503,19 @@ TAOS_RES *taos_consume(TAOS_SUB *tsub) { SSqlCmd *pCmd = &pSql->cmd; STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0); SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0); - if (taosArrayGetSize(pSub->progress) > 0) { // fix crash in single tabel subscription - pQueryInfo->window.skey = ((SSubscriptionProgress*)taosArrayGet(pSub->progress, 0))->key; - tscDebug("subscribe:%s set subscribe skey:%"PRId64, pSub->topic, pQueryInfo->window.skey); + if (taosArrayGetSize(pSub->progress) > 0) { // fix crash in single table subscription + + size_t size = taosArrayGetSize(pSub->progress); + TSKEY s = INT64_MAX; + for(int32_t i = 0; i < size; ++i) { + TSKEY k = ((SSubscriptionProgress*)taosArrayGet(pSub->progress, i))->key; + if (s > k) { + s = k; + } + } + + pQueryInfo->window.skey = s; + tscDebug("subscribe:%s set next round subscribe skey:%"PRId64, pSub->topic, pQueryInfo->window.skey); } if (pSub->pTimer == NULL) { diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index e577291966318e659848a42173f5a94f58473550..fbfc15bbc87bfbd292e8dd12cf125382153c7593 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -74,14 +74,14 @@ static bool allSubqueryDone(SSqlObj *pParentSql) { SSubqueryState *subState = &pParentSql->subState; //lock in caller - + tscDebug("%p total subqueries: %d", pParentSql, subState->numOfSub); for (int i = 0; i < subState->numOfSub; i++) { if (0 == subState->states[i]) { - tscDebug("%p subquery:%p,%d is NOT finished, total:%d", pParentSql, pParentSql->pSubs[i], i, subState->numOfSub); + tscDebug("%p subquery:%p, index: %d NOT finished, abort query completion check", pParentSql, pParentSql->pSubs[i], i); done = false; break; } else { - tscDebug("%p subquery:%p,%d is finished, total:%d", pParentSql, pParentSql->pSubs[i], i, subState->numOfSub); + tscDebug("%p subquery:%p, index: %d finished", pParentSql, pParentSql->pSubs[i], i); } } @@ -453,7 +453,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) { pSubQueryInfo->tsBuf = NULL; // free result for async object will also free sqlObj - assert(tscSqlExprNumOfExprs(pSubQueryInfo) == 1); // ts_comp query only requires one resutl columns + assert(tscSqlExprNumOfExprs(pSubQueryInfo) == 1); // ts_comp query only requires one result columns taos_free_result(pPrevSub); SSqlObj *pNew = createSubqueryObj(pSql, (int16_t) i, tscJoinQueryCallback, pSupporter, TSDB_SQL_SELECT, NULL); @@ -507,6 +507,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) { SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, 0); int16_t funcId = pExpr->functionId; + // add the invisible timestamp column if ((pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) || (funcId != TSDB_FUNC_TS && funcId != TSDB_FUNC_TS_DUMMY && funcId != TSDB_FUNC_PRJ)) { @@ -847,6 +848,8 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow SSqlRes* pRes = &pSql->res; SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); + + // todo, the type may not include TSDB_QUERY_TYPE_TAG_FILTER_QUERY assert(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY)); if (pParentSql->res.code != TSDB_CODE_SUCCESS) { @@ -2643,12 +2646,17 @@ static SSqlObj *tscCreateSTableSubquery(SSqlObj *pSql, SRetrieveSupport *trsuppo SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0); pQueryInfo->type |= TSDB_QUERY_TYPE_STABLE_SUBQUERY; + + // clear the limit/offset info, since it should not be sent to vnode to be executed. + pQueryInfo->limit.limit = -1; + pQueryInfo->limit.offset = 0; + assert(pQueryInfo->numOfTables == 1 && pNew->cmd.numOfClause == 1 && trsupport->subqueryIndex < pSql->subState.numOfSub); // launch subquery for each vnode, so the subquery index equals to the vgroupIndex. STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, table_index); pTableMetaInfo->vgroupIndex = trsupport->subqueryIndex; - + pSql->pSubs[trsupport->subqueryIndex] = pNew; } @@ -3102,30 +3110,6 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) { } } -static UNUSED_FUNC void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) { - SSqlRes *pRes = &pSql->res; - - if (pRes->tsrow[columnIndex] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) { - // convert unicode to native code in a temporary buffer extra one byte for terminated symbol - if (pRes->buffer[columnIndex] == NULL) { - pRes->buffer[columnIndex] = malloc(pField->bytes + TSDB_NCHAR_SIZE); - } - - /* string terminated char for binary data*/ - memset(pRes->buffer[columnIndex], 0, pField->bytes + TSDB_NCHAR_SIZE); - - int32_t length = taosUcs4ToMbs(pRes->tsrow[columnIndex], pRes->length[columnIndex], pRes->buffer[columnIndex]); - if ( length >= 0 ) { - pRes->tsrow[columnIndex] = (unsigned char*)pRes->buffer[columnIndex]; - pRes->length[columnIndex] = length; - } else { - tscError("%p charset:%s to %s. val:%s convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)pRes->tsrow[columnIndex]); - pRes->tsrow[columnIndex] = NULL; - pRes->length[columnIndex] = 0; - } - } -} - char *getArithmeticInputSrc(void *param, const char *name, int32_t colId) { SArithmeticSupport *pSupport = (SArithmeticSupport *) param; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 578a7df1493b23792791a29bf0acf43c6e38b719..8fd4e6e6f1f143f8569b77c4273e2f1ffe51710a 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -97,6 +97,22 @@ bool tscQueryTags(SQueryInfo* pQueryInfo) { return true; } +bool tscQueryBlockInfo(SQueryInfo* pQueryInfo) { + int32_t numOfCols = (int32_t) tscSqlExprNumOfExprs(pQueryInfo); + + for (int32_t i = 0; i < numOfCols; ++i) { + SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i); + int32_t functId = pExpr->functionId; + + // "select count(tbname)" query + if (functId == TSDB_FUNC_BLKINFO) { + return true; + } + } + + return false; +} + bool tscIsTwoStageSTableQuery(SQueryInfo* pQueryInfo, int32_t tableIndex) { if (pQueryInfo == NULL) { return false; @@ -1722,10 +1738,15 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo) { pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField)); assert(pQueryInfo->exprList == NULL); - pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES); - pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); - pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX; - pQueryInfo->resColumnId= -1000; + pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES); + pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); + pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX; + pQueryInfo->resColumnId = -1000; + pQueryInfo->limit.limit = -1; + pQueryInfo->limit.offset = 0; + + pQueryInfo->slimit.limit = -1; + pQueryInfo->slimit.offset = 0; } int32_t tscAddSubqueryInfo(SSqlCmd* pCmd) { diff --git a/src/common/inc/tname.h b/src/common/inc/tname.h index b651913d7384bac75eea7c9644b501b781c47e33..465b298973cbccdf380150bdce46a09b56594801 100644 --- a/src/common/inc/tname.h +++ b/src/common/inc/tname.h @@ -33,7 +33,7 @@ typedef struct SDataStatis { typedef struct SColumnInfoData { SColumnInfo info; - void* pData; // the corresponding block data in memory + char* pData; // the corresponding block data in memory } SColumnInfoData; typedef struct SResPair { diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index af933fa4e9cb194034b68643cdf23dbb6811ee02..4d170399da96821dee447f7709c46c0d015e5872 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -252,7 +252,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_QRY_IN_EXEC TAOS_DEF_ERROR_CODE(0, 0x0709) //"Multiple retrieval of this query") #define TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW TAOS_DEF_ERROR_CODE(0, 0x070A) //"Too many time window in query") #define TSDB_CODE_QRY_NOT_ENOUGH_BUFFER TAOS_DEF_ERROR_CODE(0, 0x070B) //"Query buffer limit has reached") -#define TSDB_CODE_QRY_INCONSISTAN TAOS_DEF_ERROR_CODE(0, 0x070C) //"File inconsistance in replica") +#define TSDB_CODE_QRY_INCONSISTAN TAOS_DEF_ERROR_CODE(0, 0x070C) //"File inconsistency in replica") // grant diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index f740575b7a0a59c62cd5819dfac1831f26565bec..7de11a09ac41802b3724fee81eb41b96217915ec 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -394,7 +394,7 @@ typedef struct SColIndex { int16_t colId; // column id int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag uint16_t flag; // denote if it is a tag or a normal column - char name[TSDB_COL_NAME_LEN]; + char name[TSDB_COL_NAME_LEN]; // TODO remove it } SColIndex; /* sql function msg, to describe the message to vnode about sql function @@ -402,7 +402,10 @@ typedef struct SColIndex { typedef struct SSqlFuncMsg { int16_t functionId; int16_t numOfParams; + int16_t resColId; // result column id, id of the current output column + int16_t colType; + int16_t colBytes; SColIndex colInfo; struct ArgElem { diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 78cd2927c7b85d39dd0a965971334e4c3b1cbddd..09444bb8e4b2c6cd45ce087a3444338d140a90ae 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -158,13 +158,18 @@ int32_t tsdbInsertData(STsdbRepo *repo, SSubmitMsg *pMsg, SShellSubmitRspMsg *pR typedef void *TsdbQueryHandleT; // Use void to hide implementation details -// query condition to build vnode iterator +#define BLOCK_LOAD_OFFSET_SEQ_ORDER 1 +#define BLOCK_LOAD_TABLE_SEQ_ORDER 2 +#define BLOCK_LOAD_TABLE_RR_ORDER 3 + +// query condition to build multi-table data block iterator typedef struct STsdbQueryCond { STimeWindow twindow; int32_t order; // desc|asc order to iterate the data block int32_t numOfCols; SColumnInfo *colList; bool loadExternalRows; // load external rows or not + int32_t type; // data block load type: } STsdbQueryCond; typedef struct SMemRef { @@ -181,17 +186,31 @@ typedef struct SDataBlockInfo { int32_t tid; } SDataBlockInfo; +typedef struct SFileBlockInfo { + int32_t numOfRows; +} SFileBlockInfo; + typedef struct { void *pTable; TSKEY lastKey; } STableKeyInfo; typedef struct { - size_t numOfTables; + uint32_t numOfTables; SArray * pGroupList; SHashObj *map; // speedup acquire the tableQueryInfo by table uid } STableGroupInfo; +typedef struct { + uint16_t rowSize; + uint16_t numOfFiles; + uint32_t numOfTables; + uint64_t totalSize; + int32_t firstSeekTimeUs; + uint32_t numOfRowsInMemTable; + SArray *dataBlockInfos; +} STableBlockDist; + /** * Get the data block iterator, starting from position according to the query condition * @@ -252,16 +271,7 @@ int64_t tsdbGetNumOfRowsInMemTable(TsdbQueryHandleT* pHandle); * @param pQueryHandle * @return */ -bool tsdbNextDataBlock(TsdbQueryHandleT *pQueryHandle); -/** - * move to next block if exists but not merge data in memtable - * - * @param pQueryHandle - * @return - */ -bool tsdbNextDataBlockWithoutMerge(TsdbQueryHandleT *pQueryHandle); - -SArray* tsdbGetExternalRow(TsdbQueryHandleT *pHandle, SMemRef* pMemRef, int16_t type); +bool tsdbNextDataBlock(TsdbQueryHandleT pQueryHandle); /** * Get current data block information @@ -306,7 +316,7 @@ int32_t tsdbQuerySTableByTagCond(STsdbRepo *tsdb, uint64_t uid, TSKEY key, const SColIndex *pColIndex, int32_t numOfCols); /** - * destory the created table group list, which is generated by tag query + * destroy the created table group list, which is generated by tag query * @param pGroupList */ void tsdbDestroyTableGroup(STableGroupInfo *pGroupList); @@ -336,6 +346,12 @@ int32_t tsdbGetTableGroupFromIdList(STsdbRepo *tsdb, SArray *pTableIdList, STabl */ void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle); +void tsdbResetQueryHandle(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond); + +void tsdbResetQueryHandleForNewTable(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond, STableGroupInfo* groupList); + +int32_t tsdbGetFileBlocksDistInfo(TsdbQueryHandleT* queryHandle, STableBlockDist* pTableBlockInfo); + /** * get the statistics of repo usage * @param repo. point to the tsdbrepo diff --git a/src/inc/ttokendef.h b/src/inc/ttokendef.h index 5ee0ec376a292360d473e81f56ff1ed487a5e10e..ba4ae884c56c2d2a6e551952c8cb82e04d279b88 100644 --- a/src/inc/ttokendef.h +++ b/src/inc/ttokendef.h @@ -191,52 +191,18 @@ #define TK_STATEMENT 172 #define TK_TRIGGER 173 #define TK_VIEW 174 -#define TK_COUNT 175 -#define TK_SUM 176 -#define TK_AVG 177 -#define TK_MIN 178 -#define TK_MAX 179 -#define TK_FIRST 180 -#define TK_LAST 181 -#define TK_TOP 182 -#define TK_BOTTOM 183 -#define TK_STDDEV 184 -#define TK_PERCENTILE 185 -#define TK_APERCENTILE 186 -#define TK_LEASTSQUARES 187 -#define TK_HISTOGRAM 188 -#define TK_DIFF 189 -#define TK_SPREAD 190 -#define TK_TWA 191 -#define TK_INTERP 192 -#define TK_LAST_ROW 193 -#define TK_RATE 194 -#define TK_IRATE 195 -#define TK_SUM_RATE 196 -#define TK_SUM_IRATE 197 -#define TK_AVG_RATE 198 -#define TK_AVG_IRATE 199 -#define TK_TBID 200 -#define TK_SEMI 201 -#define TK_NONE 202 -#define TK_PREV 203 -#define TK_LINEAR 204 -#define TK_IMPORT 205 -#define TK_METRIC 206 -#define TK_TBNAME 207 -#define TK_JOIN 208 -#define TK_METRICS 209 -#define TK_INSERT 210 -#define TK_INTO 211 -#define TK_VALUES 212 - - - - - - - - +#define TK_SEMI 175 +#define TK_NONE 176 +#define TK_PREV 177 +#define TK_LINEAR 178 +#define TK_IMPORT 179 +#define TK_METRIC 180 +#define TK_TBNAME 181 +#define TK_JOIN 182 +#define TK_METRICS 183 +#define TK_INSERT 184 +#define TK_INTO 185 +#define TK_VALUES 186 #define TK_SPACE 300 diff --git a/src/inc/ttype.h b/src/inc/ttype.h index 2f6b80f89d024e3d286ae20b41f645a073ddc174..662a23bfdbc52e432d2bcfbdac5c43cfba5d60dc 100644 --- a/src/inc/ttype.h +++ b/src/inc/ttype.h @@ -171,10 +171,10 @@ extern tDataTypeDescriptor tDataTypes[15]; bool isValidDataType(int32_t type); -void setVardataNull(char* val, int32_t type); -void setNull(char *val, int32_t type, int32_t bytes); -void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems); -void* getNullValue(int32_t type); +void setVardataNull(char* val, int32_t type); +void setNull(char *val, int32_t type, int32_t bytes); +void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems); +void *getNullValue(int32_t type); void assignVal(char *val, const char *src, int32_t len, int32_t type); void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf); diff --git a/src/query/inc/qAggMain.h b/src/query/inc/qAggMain.h index 7122f63593c64a6bffd6f3d53cd8ef21eca800ff..c59067c4b357aa084cd6f31c39f3038075d18a82 100644 --- a/src/query/inc/qAggMain.h +++ b/src/query/inc/qAggMain.h @@ -26,6 +26,7 @@ extern "C" { #include "taosdef.h" #include "trpc.h" #include "tvariant.h" +#include "tsdb.h" #define TSDB_FUNC_INVALID_ID -1 #define TSDB_FUNC_COUNT 0 @@ -70,15 +71,17 @@ extern "C" { #define TSDB_FUNC_AVG_IRATE 34 #define TSDB_FUNC_TID_TAG 35 -#define TSDB_FUNC_HISTOGRAM 36 -#define TSDB_FUNC_HLL 37 -#define TSDB_FUNC_MODE 38 -#define TSDB_FUNC_SAMPLE 39 -#define TSDB_FUNC_CEIL 40 -#define TSDB_FUNC_FLOOR 41 -#define TSDB_FUNC_ROUND 42 -#define TSDB_FUNC_MAVG 43 -#define TSDB_FUNC_CSUM 44 +#define TSDB_FUNC_BLKINFO 36 + +#define TSDB_FUNC_HISTOGRAM 37 +#define TSDB_FUNC_HLL 38 +#define TSDB_FUNC_MODE 39 +#define TSDB_FUNC_SAMPLE 40 +#define TSDB_FUNC_CEIL 41 +#define TSDB_FUNC_FLOOR 42 +#define TSDB_FUNC_ROUND 43 +#define TSDB_FUNC_MAVG 44 +#define TSDB_FUNC_CSUM 45 #define TSDB_FUNCSTATE_SO 0x1u // single output @@ -214,13 +217,14 @@ typedef struct SAggFunctionInfo { void (*xFinalize)(SQLFunctionCtx *pCtx); void (*mergeFunc)(SQLFunctionCtx *pCtx); - int32_t (*dataReqFunc)(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId); + int32_t (*dataReqFunc)(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId); } SAggFunctionInfo; #define GET_RES_INFO(ctx) ((ctx)->resultInfo) int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type, int16_t *len, int32_t *interBytes, int16_t extLength, bool isSuperTable); +int32_t isValidFunction(const char* name, int32_t len); #define IS_STREAM_QUERY_VALID(x) (((x)&TSDB_FUNCSTATE_STREAM) != 0) #define IS_MULTIOUTPUT(x) (((x)&TSDB_FUNCSTATE_MO) != 0) @@ -242,12 +246,16 @@ typedef struct STwaInfo { STimeWindow win; } STwaInfo; +struct SBufferWriter; +void blockDistInfoToBinary(STableBlockDist* pDist, struct SBufferWriter* bw); +void blockDistInfoFromBinary(const char* data, int32_t len, STableBlockDist* pDist); + /* global sql function array */ extern struct SAggFunctionInfo aAggs[]; extern int32_t functionCompatList[]; // compatible check array list -bool topbot_datablock_filter(SQLFunctionCtx *pCtx, int32_t functionId, const char *minval, const char *maxval); +bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const char *maxval); /** * the numOfRes should be kept, since it may be used later @@ -258,14 +266,14 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, int32_t functionId, const cha (_r)->initialized = false; \ } while (0) -static FORCE_INLINE void initResultInfo(SResultRowCellInfo *pResInfo, uint32_t bufLen) { +static FORCE_INLINE void initResultInfo(SResultRowCellInfo *pResInfo, int32_t bufLen) { pResInfo->initialized = true; // the this struct has been initialized flag pResInfo->complete = false; pResInfo->hasResult = false; pResInfo->numOfRes = 0; - memset(GET_ROWCELL_INTERBUF(pResInfo), 0, (size_t)bufLen); + memset(GET_ROWCELL_INTERBUF(pResInfo), 0, bufLen); } #ifdef __cplusplus diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index ec1261da0a45ad24985ebf51b9b16c2acfad7709..0d8870a377fb76803aee5f2a00d94454a35bea87 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -12,8 +12,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef TDENGINE_QUERYEXECUTOR_H -#define TDENGINE_QUERYEXECUTOR_H +#ifndef TDENGINE_QEXECUTOR_H +#define TDENGINE_QEXECUTOR_H #include "os.h" @@ -37,30 +37,24 @@ typedef int32_t (*__block_search_fn_t)(char* data, int32_t num, int64_t key, int #define Q_STATUS_EQUAL(p, s) (((p) & (s)) != 0u) #define QUERY_IS_ASC_QUERY(q) (GET_FORWARD_DIRECTION_FACTOR((q)->order.order) == QUERY_ASC_FORWARD_STEP) -#define SET_STABLE_QUERY_OVER(_q) ((_q)->tableIndex = (int32_t)((_q)->tableqinfoGroupInfo.numOfTables)) -#define IS_STASBLE_QUERY_OVER(_q) ((_q)->tableIndex >= (int32_t)((_q)->tableqinfoGroupInfo.numOfTables)) - #define GET_TABLEGROUP(q, _index) ((SArray*) taosArrayGetP((q)->tableqinfoGroupInfo.pGroupList, (_index))) +#define GET_NUM_OF_RESULTS(_r) (((_r)->outputBuf) == NULL? 0:((_r)->outputBuf)->info.rows) + enum { // when query starts to execute, this status will set QUERY_NOT_COMPLETED = 0x1u, - /* result output buffer is full, current query is paused. - * this status is only exist in group-by clause and diff/add/division/multiply/ query. - */ - QUERY_RESBUF_FULL = 0x2u, - /* query is over * 1. this status is used in one row result query process, e.g., count/sum/first/last/ avg...etc. * 2. when all data within queried time window, it is also denoted as query_completed */ - QUERY_COMPLETED = 0x4u, + QUERY_COMPLETED = 0x2u, /* when the result is not completed return to client, this status will be * usually used in case of interval query with interpolation option */ - QUERY_OVER = 0x8u, + QUERY_OVER = 0x4u, }; typedef struct SResultRowPool { @@ -86,13 +80,13 @@ typedef struct SSqlGroupbyExpr { typedef struct SResultRow { int32_t pageId; // pageId & rowId is the position of current result in disk-based output buffer - int32_t rowId:29; // row index in buffer page + int32_t offset:29; // row index in buffer page bool startInterp; // the time window start timestamp has done the interpolation already. bool endInterp; // the time window end timestamp has done the interpolation already. bool closed; // this result status: closed or opened uint32_t numOfRows; // number of rows of current time window SResultRowCellInfo* pCellInfo; // For each result column, there is a resultInfo - union {STimeWindow win; char* key;}; // start key of current time window + union {STimeWindow win; char* key;}; // start key of current result row } SResultRow; typedef struct SGroupResInfo { @@ -106,12 +100,11 @@ typedef struct SGroupResInfo { * If the number of generated results is greater than this value, * query query will be halt and return results to client immediate. */ -typedef struct SResultRec { +typedef struct SRspResultInfo { int64_t total; // total generated result size in rows - int64_t rows; // current result set size in rows - int64_t capacity; // capacity of current result output buffer + int32_t capacity; // capacity of current result output buffer int32_t threshold; // result size threshold in rows. -} SResultRec; +} SRspResultInfo; typedef struct SResultRowInfo { SResultRow** pResult; // result list @@ -138,7 +131,6 @@ typedef struct SSingleColumnFilterInfo { typedef struct STableQueryInfo { TSKEY lastKey; int32_t groupIndex; // group id in table list - int16_t queryRangeSet; // denote if the query range is set, only available for interval query tVariant tag; STimeWindow win; STSCursor cur; @@ -179,82 +171,135 @@ typedef struct { SArray* pResult; // SArray } SInterResult; +typedef struct SSDataBlock { + SDataStatis *pBlockStatis; + SArray *pDataBlock; + SDataBlockInfo info; +} SSDataBlock; + typedef struct SQuery { + SLimitVal limit; + + bool stableQuery; // super table query or not + bool topBotQuery; // TODO used bitwise flag + bool groupbyColumn; // denote if this is a groupby normal column query + bool hasTagResults; // if there are tag values in final result or not + bool timeWindowInterpo;// if the time window start/end required interpolation + bool queryWindowIdentical; // all query time windows are identical for all tables in one group + bool queryBlockDist; // if query data block distribution + bool stabledev; // super table stddev query + int32_t interBufSize; // intermediate buffer sizse + + SOrderVal order; int16_t numOfCols; int16_t numOfTags; - SOrderVal order; + STimeWindow window; SInterval interval; int16_t precision; int16_t numOfOutput; int16_t fillType; int16_t checkResultBuf; // check if the buffer is full during scan each block - SLimitVal limit; int32_t srcRowSize; // todo extract struct int32_t resultRowSize; + int32_t intermediateResultRowSize; // intermediate result row size, in case of top-k query. int32_t maxSrcColumnSize; int32_t tagLen; // tag value length of current query - SSqlGroupbyExpr* pGroupbyExpr; SExprInfo* pExpr1; SExprInfo* pExpr2; int32_t numOfExpr2; - SColumnInfo* colList; SColumnInfo* tagColList; int32_t numOfFilterCols; int64_t* fillVal; - uint32_t status; // query status - SResultRec rec; - int32_t pos; - tFilePage** sdata; - STableQueryInfo* current; - int32_t numOfCheckedBlocks; // number of check data blocks - SOrderedPrjQueryInfo prjInfo; // limit value for each vgroup, only available in global order projection query. SSingleColumnFilterInfo* pFilterInfo; + + STableQueryInfo* current; + void* tsdb; + SMemRef memRef; + STableGroupInfo tableGroupInfo; // table list SArray + int32_t vgId; } SQuery; +typedef SSDataBlock* (*__operator_fn_t)(void* param); +typedef void (*__optr_cleanup_fn_t)(void* param, int32_t num); + +struct SOperatorInfo; + typedef struct SQueryRuntimeEnv { - jmp_buf env; - SQuery* pQuery; - SQLFunctionCtx* pCtx; - int32_t numOfRowsPerPage; - uint16_t* offset; - uint16_t scanFlag; // denotes reversed scan of data or not - SFillInfo* pFillInfo; - SResultRowInfo resultRowInfo; - - SQueryCostInfo summary; - void* pQueryHandle; - void* pSecQueryHandle; // another thread for - bool stableQuery; // super table query or not - bool topBotQuery; // TODO used bitwise flag - bool groupbyColumn; // denote if this is a groupby normal column query - bool hasTagResults; // if there are tag values in final result or not - bool timeWindowInterpo;// if the time window start/end required interpolation - bool queryWindowIdentical; // all query time windows are identical for all tables in one group - bool queryBlockDist; // if query data block distribution - bool stabledev; // super table stddev query - int32_t interBufSize; // intermediate buffer sizse - int32_t prevGroupId; // previous executed group id - SDiskbasedResultBuf* pResultBuf; // query result buffer based on blocked-wised disk file - SHashObj* pResultRowHashTable; // quick locate the window object for each result - char* keyBuf; // window key buffer - SResultRowPool* pool; // window result object pool - - int32_t* rowCellInfoOffset;// offset value for each row result cell info - char** prevRow; - - SArray* prevResult; // intermediate result, SArray - STSBuf* pTsBuf; // timestamp filter list - STSCursor cur; - - char* tagVal; // tag value of current data block - SArithmeticSupport *sasArray; + jmp_buf env; + SQuery* pQuery; + uint32_t status; // query status + void* qinfo; + uint8_t scanFlag; // denotes reversed scan of data or not + void* pQueryHandle; + + int32_t prevGroupId; // previous executed group id + SDiskbasedResultBuf* pResultBuf; // query result buffer based on blocked-wised disk file + SHashObj* pResultRowHashTable; // quick locate the window object for each result + char* keyBuf; // window key buffer + SResultRowPool* pool; // window result object pool + char** prevRow; + + SArray* prevResult; // intermediate result, SArray + STSBuf* pTsBuf; // timestamp filter list + STSCursor cur; + + char* tagVal; // tag value of current data block + SArithmeticSupport *sasArray; + + SSDataBlock *outputBuf; + STableGroupInfo tableqinfoGroupInfo; // this is a group array list, including SArray structure + struct SOperatorInfo *proot; + struct SOperatorInfo *pTableScanner; // table scan operator + SGroupResInfo groupResInfo; + int64_t currentOffset; // dynamic offset value + + SRspResultInfo resultInfo; + SHashObj *pTableRetrieveTsMap; } SQueryRuntimeEnv; +enum { + OP_IN_EXECUTING = 1, + OP_RES_TO_RETURN = 2, + OP_EXEC_DONE = 3, +}; + +enum OPERATOR_TYPE_E { + OP_TableScan = 1, + OP_DataBlocksOptScan = 2, + OP_TableSeqScan = 3, + OP_TagScan = 4, + OP_TableBlockInfoScan= 5, + OP_Aggregate = 6, + OP_Arithmetic = 7, + OP_Groupby = 8, + OP_Limit = 9, + OP_Offset = 10, + OP_TimeInterval = 11, + OP_Fill = 12, + OP_MultiTableAggregate = 13, + OP_MultiTableTimeInterval = 14, +}; + +typedef struct SOperatorInfo { + uint8_t operatorType; + bool blockingOptr; // block operator or not + uint8_t status; // denote if current operator is completed + int32_t numOfOutput; // number of columns of the current operator results + char *name; // name, used to show the query execution plan + void *info; // extension attribution + SExprInfo *pExpr; + SQueryRuntimeEnv *pRuntimeEnv; + + struct SOperatorInfo *upstream; + __operator_fn_t exec; + __optr_cleanup_fn_t cleanup; +} SOperatorInfo; + enum { QUERY_RESULT_NOT_READY = 1, QUERY_RESULT_READY = 2, @@ -262,23 +307,11 @@ enum { typedef struct SQInfo { void* signature; - int32_t code; // error code to returned to client - int64_t owner; // if it is in execution - void* tsdb; - SMemRef memRef; - int32_t vgId; - STableGroupInfo tableGroupInfo; // table list SArray - STableGroupInfo tableqinfoGroupInfo; // this is a group array list, including SArray structure - SQueryRuntimeEnv runtimeEnv; - SHashObj* arrTableIdInfo; - int32_t groupIndex; + int32_t code; // error code to returned to client + int64_t owner; // if it is in execution - /* - * the query is executed position on which meter of the whole list. - * when the index reaches the last one of the list, it means the query is completed. - */ - int32_t tableIndex; - SGroupResInfo groupResInfo; + SQueryRuntimeEnv runtimeEnv; + SQuery query; void* pBuf; // allocated buffer for STableQueryInfo, sizeof(STableQueryInfo)*numOfTables; pthread_mutex_t lock; // used to synchronize the rsp/query threads @@ -287,6 +320,7 @@ typedef struct SQInfo { void* rspContext; // response context int64_t startExecTs; // start to exec timestamp char* sql; // query sql string + SQueryCostInfo summary; } SQInfo; typedef struct SQueryParam { @@ -305,10 +339,85 @@ typedef struct SQueryParam { SSqlGroupbyExpr *pGroupbyExpr; } SQueryParam; +typedef struct STableScanInfo { + void *pQueryHandle; + int32_t numOfBlocks; + int32_t numOfSkipped; + int32_t numOfBlockStatis; + int64_t numOfRows; + + int32_t order; // scan order + int32_t times; // repeat counts + int32_t current; + int32_t reverseTimes; // 0 by default + + SQLFunctionCtx *pCtx; // next operator query context + SResultRowInfo *pResultRowInfo; + int32_t *rowCellInfoOffset; + SExprInfo *pExpr; + SSDataBlock block; + bool loadExternalRows; // load external rows (prev & next rows) + int32_t numOfOutput; + int64_t elapsedTime; + + int32_t tableIndex; +} STableScanInfo; + +typedef struct STagScanInfo { + SColumnInfo* pCols; + SSDataBlock* pRes; + int32_t totalTables; + int32_t currentIndex; +} STagScanInfo; + +typedef struct SOptrBasicInfo { + SResultRowInfo resultRowInfo; + int32_t *rowCellInfoOffset; // offset value for each row result cell info + SQLFunctionCtx *pCtx; + SSDataBlock *pRes; +} SOptrBasicInfo; + +typedef struct SOptrBasicInfo STableIntervalOperatorInfo; + +typedef struct SAggOperatorInfo { + SOptrBasicInfo binfo; + uint32_t seed; +} SAggOperatorInfo; + +typedef struct SArithOperatorInfo { + SOptrBasicInfo binfo; + int32_t bufCapacity; + uint32_t seed; +} SArithOperatorInfo; + +typedef struct SLimitOperatorInfo { + int64_t limit; + int64_t total; +} SLimitOperatorInfo; + +typedef struct SOffsetOperatorInfo { + int64_t offset; +} SOffsetOperatorInfo; + +typedef struct SFillOperatorInfo { + SFillInfo *pFillInfo; + SSDataBlock *pRes; + int64_t totalInputRows; +} SFillOperatorInfo; + +typedef struct SGroupbyOperatorInfo { + SOptrBasicInfo binfo; + int32_t colIndex; + char *prevData; // previous group by value +} SGroupbyOperatorInfo; + void freeParam(SQueryParam *param); int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param); int32_t createQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, SSqlFuncMsg **pExprMsg, SColumnInfo* pTagCols); +int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, + SSqlFuncMsg **pExprMsg, SExprInfo *prevExpr); + SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code); SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr, SExprInfo *pExprs, SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery, char* sql); @@ -318,13 +427,9 @@ void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters); bool isQueryKilled(SQInfo *pQInfo); int32_t checkForQueryBuf(size_t numOfTables); bool doBuildResCheck(SQInfo* pQInfo); -void setQueryStatus(SQuery *pQuery, int8_t status); +void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status); bool onlyQueryTags(SQuery* pQuery); -void buildTagQueryResult(SQInfo *pQInfo); -void stableQueryImpl(SQInfo *pQInfo); -void buildTableBlockDistResult(SQInfo *pQInfo); -void tableQueryImpl(SQInfo *pQInfo); bool isValidQInfo(void *param); int32_t doDumpQueryResult(SQInfo *pQInfo, char *data); @@ -336,4 +441,4 @@ void freeQInfo(SQInfo *pQInfo); int32_t getMaximumIdleDurationSec(); -#endif // TDENGINE_QUERYEXECUTOR_H +#endif // TDENGINE_QEXECUTOR_H diff --git a/src/query/inc/qFill.h b/src/query/inc/qFill.h index aa6df9279acb9e3cecf20d71f726974ee89a4030..00ac86caf4a079e01ad239496370d97ac28e84f2 100644 --- a/src/query/inc/qFill.h +++ b/src/query/inc/qFill.h @@ -24,6 +24,8 @@ extern "C" { #include "qExtbuffer.h" #include "taosdef.h" +struct SSDataBlock; + typedef struct { STColumn col; // column info int16_t functionId; // sql function id @@ -78,7 +80,7 @@ void* taosDestroyFillInfo(SFillInfo *pFillInfo); void taosFillSetStartInfo(SFillInfo* pFillInfo, int32_t numOfRows, TSKEY endKey); -void taosFillSetDataBlockFromFilePage(SFillInfo* pFillInfo, const tFilePage** pInput); +void taosFillSetInputDataBlock(SFillInfo* pFillInfo, const struct SSDataBlock* pInput); void taosFillCopyInputDataFromOneFilePage(SFillInfo* pFillInfo, const tFilePage* pInput); @@ -88,7 +90,7 @@ int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, int64_t ekey, int32_t int32_t taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* point1, SPoint* point2, int32_t inputType); -int64_t taosFillResultDataBlock(SFillInfo* pFillInfo, tFilePage** output, int32_t capacity); +int64_t taosFillResultDataBlock(SFillInfo* pFillInfo, void** output, int32_t capacity); #ifdef __cplusplus } diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index 704df9f3f29cc0653c353ed194e02e72cb4c5fb2..e46af8c29891cf52fbbac97c6afb42e0d0571215 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -55,7 +55,6 @@ typedef struct SResultBufStatis { } SResultBufStatis; typedef struct SDiskbasedResultBuf { - int32_t numOfRowsPerPage; int32_t numOfPages; int64_t totalBufSize; int64_t fileSize; // disk file size @@ -77,7 +76,7 @@ typedef struct SDiskbasedResultBuf { SResultBufStatis statis; } SDiskbasedResultBuf; -#define DEFAULT_INTERN_BUF_PAGE_SIZE (256L) // in bytes +#define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) // in bytes #define PAGE_INFO_INITIALIZER (SPageDiskInfo){-1, -1} /** @@ -89,8 +88,7 @@ typedef struct SDiskbasedResultBuf { * @param handle * @return */ -int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t rowSize, int32_t pagesize, - int32_t inMemBufSize, const void* handle); +int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t pagesize, int32_t inMemBufSize, const void* handle); /** * @@ -101,13 +99,6 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t ro */ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId); -/** - * - * @param pResultBuf - * @return - */ -size_t getNumOfRowsPerPage(const SDiskbasedResultBuf* pResultBuf); - /** * * @param pResultBuf diff --git a/src/query/inc/qSqlparser.h b/src/query/inc/qSqlparser.h index 33348c85652a9d207e58c6f83346c4231df56962..0ad502994008044c27b757f54314cb77a6cf5707 100644 --- a/src/query/inc/qSqlparser.h +++ b/src/query/inc/qSqlparser.h @@ -45,7 +45,7 @@ typedef struct SLimitVal { typedef struct SOrderVal { uint32_t order; - int32_t orderColId; + int32_t orderColId; } SOrderVal; typedef struct tVariantListItem { @@ -185,19 +185,32 @@ typedef struct SSqlInfo { }; } SSqlInfo; +#define NON_ARITHMEIC_EXPR 0 +#define NORMAL_ARITHMETIC 1 +#define AGG_ARIGHTMEIC 2 + +enum SQL_NODE_TYPE { + SQL_NODE_TABLE_COLUMN= 1, + SQL_NODE_SQLFUNCTION = 2, + SQL_NODE_VALUE = 3, + SQL_NODE_EXPR = 4, +}; + typedef struct tSQLExpr { - uint32_t nSQLOptr; // TK_FUNCTION: sql function, TK_LE: less than(binary expr) - - // the full sql string of function(col, param), which is actually the raw - // field name, since the function name is kept in nSQLOptr already + uint16_t type; // sql node type + uint32_t tokenId; // TK_FUNCTION: sql function, TK_LE: less than(binary expr) + + // the whole string of the function(col, param), while the function name is kept in token SStrToken operand; - SStrToken colInfo; // field id - tVariant val; // value only for string, float, int + uint32_t functionId; // function id + + SStrToken colInfo; // table column info + tVariant value; // the use input value SStrToken token; // original sql expr string struct tSQLExpr *pLeft; // left child struct tSQLExpr *pRight; // right child - struct tSQLExprList *pParam; // function parameters + struct tSQLExprList *pParam; // function parameters list } tSQLExpr; // used in select clause. select from xxx @@ -294,16 +307,6 @@ void tSqlSetColumnType(TAOS_FIELD *pField, SStrToken *type); void *ParseAlloc(void *(*mallocProc)(size_t)); -enum { - TSQL_NODE_TYPE_EXPR = 0x1, - TSQL_NODE_TYPE_ID = 0x2, - TSQL_NODE_TYPE_VALUE = 0x4, -}; - -#define NON_ARITHMEIC_EXPR 0 -#define NORMAL_ARITHMETIC 1 -#define AGG_ARIGHTMEIC 2 - SSqlInfo qSQLParse(const char *str); #ifdef __cplusplus diff --git a/src/query/inc/qTsbuf.h b/src/query/inc/qTsbuf.h index 5d055782c9b82a1444c97a62d429cc2ba9a53986..00cc4e897f130348b81a7d96419c1b292cacca8c 100644 --- a/src/query/inc/qTsbuf.h +++ b/src/query/inc/qTsbuf.h @@ -112,13 +112,11 @@ STSBuf* tsBufClone(STSBuf* pTSBuf); STSGroupBlockInfo* tsBufGetGroupBlockInfo(STSBuf* pTSBuf, int32_t id); -void tsBufFlush(STSBuf* pTSBuf); - +void tsBufFlush(STSBuf* pTSBuf); void tsBufResetPos(STSBuf* pTSBuf); -STSElem tsBufGetElem(STSBuf* pTSBuf); - bool tsBufNextPos(STSBuf* pTSBuf); +STSElem tsBufGetElem(STSBuf* pTSBuf); STSElem tsBufGetElemStartPos(STSBuf* pTSBuf, int32_t id, tVariant* tag); STSCursor tsBufGetCursor(STSBuf* pTSBuf); diff --git a/src/query/inc/qUtil.h b/src/query/inc/qUtil.h index d4a0c25886ad63ff5cc3e79cb0a9e84c156197cd..31dfc350a39b642631c1e9c60f713e953d6898c3 100644 --- a/src/query/inc/qUtil.h +++ b/src/query/inc/qUtil.h @@ -27,7 +27,7 @@ #define GET_RES_WINDOW_KEY_LEN(_l) ((_l) + sizeof(uint64_t)) #define curTimeWindowIndex(_winres) ((_winres)->curIndex) -#define GET_ROW_PARAM_FOR_MULTIOUTPUT(_q, tbq, sq) (((tbq) && (!sq))? (_q)->pExpr1[1].base.arg->argValue.i64:1) +#define GET_ROW_PARAM_FOR_MULTIOUTPUT(_q, tbq, sq) (((tbq) && (!(sq)))? (_q)->pExpr1[1].base.arg->argValue.i64:1) int32_t getOutputInterResultBufSize(SQuery* pQuery); @@ -44,22 +44,18 @@ void closeResultRow(SResultRowInfo* pResultRowInfo, int32_t slot); bool isResultRowClosed(SResultRowInfo *pResultRowInfo, int32_t slot); void clearResultRow(SQueryRuntimeEnv* pRuntimeEnv, SResultRow* pResultRow, int16_t type); -SResultRowCellInfo* getResultCell(SQueryRuntimeEnv* pRuntimeEnv, const SResultRow* pRow, int32_t index); +SResultRowCellInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_t* offset); static FORCE_INLINE SResultRow *getResultRow(SResultRowInfo *pResultRowInfo, int32_t slot) { assert(pResultRowInfo != NULL && slot >= 0 && slot < pResultRowInfo->size); return pResultRowInfo->pResult[slot]; } -static FORCE_INLINE char *getPosInResultPage(SQueryRuntimeEnv *pRuntimeEnv, int32_t columnIndex, SResultRow *pResult, - tFilePage* page) { - assert(pResult != NULL && pRuntimeEnv != NULL); +static FORCE_INLINE char *getPosInResultPage(SQuery *pQuery, tFilePage* page, int32_t rowOffset, int16_t offset) { + assert(rowOffset >= 0 && pQuery != NULL); - SQuery *pQuery = pRuntimeEnv->pQuery; - - int32_t realRowId = (int32_t)(pResult->rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery)); - return ((char *)page->data) + pRuntimeEnv->offset[columnIndex] * pRuntimeEnv->numOfRowsPerPage + - pQuery->pExpr1[columnIndex].bytes * realRowId; + int32_t numOfRows = (int32_t)GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery); + return ((char *)page->data) + rowOffset + offset * numOfRows; } bool isNullOperator(SColumnFilterElem *pFilter, const char* minval, const char* maxval, int16_t type); @@ -74,8 +70,6 @@ void* destroyResultRowPool(SResultRowPool* p); int32_t getNumOfAllocatedResultRows(SResultRowPool* p); int32_t getNumOfUsedResultRows(SResultRowPool* p); -bool isPointInterpoQuery(SQuery *pQuery); - typedef struct { SArray* pResult; // SArray int32_t colId; @@ -85,12 +79,14 @@ void interResToBinary(SBufferWriter* bw, SArray* pRes, int32_t tagLen); SArray* interResFromBinary(const char* data, int32_t len); void freeInterResult(void* param); -void initGroupResInfo(SGroupResInfo* pGroupResInfo, SResultRowInfo* pResultInfo, int32_t offset); +void initGroupResInfo(SGroupResInfo* pGroupResInfo, SResultRowInfo* pResultInfo); void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo); +bool hasRemainDataInCurrentGroup(SGroupResInfo* pGroupResInfo); bool hasRemainData(SGroupResInfo* pGroupResInfo); + bool incNextGroup(SGroupResInfo* pGroupResInfo); int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo); -int32_t mergeIntoGroupResult(SGroupResInfo* pGroupResInfo, SQInfo *pQInfo); +int32_t mergeIntoGroupResult(SGroupResInfo* pGroupResInfo, SQueryRuntimeEnv *pRuntimeEnv, int32_t* offset); #endif // TDENGINE_QUERYUTIL_H diff --git a/src/query/inc/sql.y b/src/query/inc/sql.y index 1bafe241e3e6cb32a102631be9e9620a4ae48429..c340ea8224b0996a35638fde1261be8bc142d8b4 100644 --- a/src/query/inc/sql.y +++ b/src/query/inc/sql.y @@ -834,7 +834,6 @@ cmd ::= KILL QUERY INTEGER(X) COLON(Z) INTEGER(Y). {X.n += (Z.n + Y.n); s %fallback ID ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CLUSTER CONFLICT COPY DATABASE DEFERRED DELIMITERS DESC DETACH EACH END EXPLAIN FAIL FOR GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY OF OFFSET RAISE REPLACE RESTRICT ROW STATEMENT TRIGGER VIEW ALL - COUNT SUM AVG MIN MAX FIRST LAST TOP BOTTOM STDDEV PERCENTILE APERCENTILE LEASTSQUARES HISTOGRAM DIFF - SPREAD TWA INTERP LAST_ROW RATE IRATE SUM_RATE SUM_IRATE AVG_RATE AVG_IRATE TBID NOW IPTOKEN SEMI NONE PREV LINEAR IMPORT + NOW IPTOKEN SEMI NONE PREV LINEAR IMPORT METRIC TBNAME JOIN METRICS STABLE NULL INSERT INTO VALUES. \ No newline at end of file diff --git a/src/query/src/qAggMain.c b/src/query/src/qAggMain.c index f99fe3f0720784db0a5e0b526dddb436a91f87d3..f18d093b89d48419e9707d606a289b3168fea8bf 100644 --- a/src/query/src/qAggMain.c +++ b/src/query/src/qAggMain.c @@ -18,6 +18,7 @@ #include "taosmsg.h" #include "texpr.h" #include "ttype.h" +#include "tsdb.h" #include "qAggMain.h" #include "qFill.h" @@ -26,11 +27,9 @@ #include "qTsbuf.h" #include "queryLog.h" -//#define GET_INPUT_DATA_LIST(x) (((char *)((x)->pInput)) + ((x)->startOffset) * ((x)->inputBytes)) #define GET_INPUT_DATA_LIST(x) ((char *)((x)->pInput)) #define GET_INPUT_DATA(x, y) (GET_INPUT_DATA_LIST(x) + (y) * (x)->inputBytes) -//#define GET_TS_LIST(x) ((TSKEY*)&((x)->ptsList[(x)->startOffset])) #define GET_TS_LIST(x) ((TSKEY*)((x)->ptsList)) #define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)]) @@ -191,6 +190,11 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *bytes = (int16_t)(dataBytes + sizeof(int16_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE); *interBytes = 0; return TSDB_CODE_SUCCESS; + } else if (functionId == TSDB_FUNC_BLKINFO) { + *type = TSDB_DATA_TYPE_BINARY; + *bytes = 16384; + *interBytes = 0; + return TSDB_CODE_SUCCESS; } if (functionId == TSDB_FUNC_COUNT) { @@ -209,7 +213,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI if (functionId == TSDB_FUNC_TS_COMP) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = sizeof(int32_t); // this results is compressed ts data + *bytes = 1; // this results is compressed ts data, only one byte *interBytes = POINTER_BYTES; return TSDB_CODE_SUCCESS; } @@ -355,6 +359,22 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI return TSDB_CODE_SUCCESS; } +// TODO use hash table +int32_t isValidFunction(const char* name, int32_t len) { + for(int32_t i = 0; i <= TSDB_FUNC_BLKINFO; ++i) { + int32_t nameLen = (int32_t) strlen(aAggs[i].name); + if (len != nameLen) { + continue; + } + + if (strncasecmp(aAggs[i].name, name, len) == 0) { + return i; + } + } + + return -1; +} + // set the query flag to denote that query is completed static void no_next_step(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); @@ -458,7 +478,7 @@ static void count_func_merge(SQLFunctionCtx *pCtx) { * @param filterCols * @return */ -int32_t count_load_data_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +int32_t countRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { if (colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { return BLK_DATA_NO_NEEDED; } else { @@ -466,7 +486,7 @@ int32_t count_load_data_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32 } } -int32_t no_data_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +int32_t noDataRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { return BLK_DATA_NO_NEEDED; } @@ -674,16 +694,16 @@ static void sum_func_merge(SQLFunctionCtx *pCtx) { } } -static int32_t statisRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +static int32_t statisRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { return BLK_DATA_STATIS_NEEDED; } -static int32_t dataBlockRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +static int32_t dataBlockRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { return BLK_DATA_ALL_NEEDED; } -// todo: if column in current data block are null, opt for this case -static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +// todo: if column in current data block are null, opt for this case +static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { if (pCtx->order == TSDB_ORDER_DESC) { return BLK_DATA_NO_NEEDED; } @@ -696,7 +716,7 @@ static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, i } } -static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { if (pCtx->order != pCtx->param[0].i64) { return BLK_DATA_NO_NEEDED; } @@ -708,7 +728,7 @@ static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, in } } -static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { if (pCtx->order == TSDB_ORDER_DESC) { return BLK_DATA_NO_NEEDED; } @@ -724,11 +744,11 @@ static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY en if (pInfo->hasResult != DATA_SET_FLAG) { return BLK_DATA_ALL_NEEDED; } else { // data in current block is not earlier than current result - return (pInfo->ts <= start) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED; + return (pInfo->ts <= w->skey) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED; } } -static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { +static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { if (pCtx->order != pCtx->param[0].i64) { return BLK_DATA_NO_NEEDED; } @@ -744,7 +764,7 @@ static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end if (pInfo->hasResult != DATA_SET_FLAG) { return BLK_DATA_ALL_NEEDED; } else { - return (pInfo->ts > end) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED; + return (pInfo->ts > w->ekey) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED; } } @@ -1359,7 +1379,21 @@ static void min_function_f(SQLFunctionCtx *pCtx, int32_t index) { } static void stddev_function(SQLFunctionCtx *pCtx) { - SStddevInfo *pStd = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SStddevInfo *pStd = GET_ROWCELL_INTERBUF(pResInfo); + + if (pCtx->currentStage == REPEAT_SCAN && pStd->stage == 0) { + pStd->stage++; + avg_finalizer(pCtx); + + pResInfo->initialized = true; // set it initialized to avoid re-initialization + + // save average value into tmpBuf, for second stage scan + SAvgInfo *pAvg = GET_ROWCELL_INTERBUF(pResInfo); + + pStd->avg = GET_DOUBLE_VAL(pCtx->pOutput); + assert((isnan(pAvg->sum) && pAvg->num == 0) || (pStd->num == pAvg->num && pStd->avg == pAvg->sum)); + } if (pStd->stage == 0) { // the first stage is to calculate average value @@ -1432,7 +1466,20 @@ static void stddev_function_f(SQLFunctionCtx *pCtx, int32_t index) { // the second stage to calculate standard deviation SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); SStddevInfo *pStd = GET_ROWCELL_INTERBUF(pResInfo); - + + if (pCtx->currentStage == REPEAT_SCAN && pStd->stage == 0) { + pStd->stage++; + avg_finalizer(pCtx); + + pResInfo->initialized = true; // set it initialized to avoid re-initialization + + // save average value into tmpBuf, for second stage scan + SAvgInfo *pAvg = GET_ROWCELL_INTERBUF(pResInfo); + + pStd->avg = GET_DOUBLE_VAL(pCtx->pOutput); + assert((isnan(pAvg->sum) && pAvg->num == 0) || (pStd->num == pAvg->num && pStd->avg == pAvg->sum)); + } + /* the first stage is to calculate average value */ if (pStd->stage == 0) { avg_function_f(pCtx, index); @@ -1574,7 +1621,7 @@ static void stddev_dst_function(SQLFunctionCtx *pCtx) { if (p == NULL) { return; } - + avg = p->avg; } @@ -1776,7 +1823,7 @@ static bool first_last_function_setup(SQLFunctionCtx *pCtx) { // todo opt for null block static void first_function(SQLFunctionCtx *pCtx) { - if (pCtx->order == TSDB_ORDER_DESC || pCtx->preAggVals.dataBlockLoaded == false) { + if (pCtx->order == TSDB_ORDER_DESC /*|| pCtx->preAggVals.dataBlockLoaded == false*/) { return; } @@ -1850,7 +1897,7 @@ static void first_dist_function(SQLFunctionCtx *pCtx) { * 1. data block that are not loaded * 2. scan data files in desc order */ - if (pCtx->order == TSDB_ORDER_DESC || pCtx->preAggVals.dataBlockLoaded == false) { + if (pCtx->order == TSDB_ORDER_DESC/* || pCtx->preAggVals.dataBlockLoaded == false*/) { return; } @@ -1921,7 +1968,7 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) { * least one data in this block that is not null.(TODO opt for this case) */ static void last_function(SQLFunctionCtx *pCtx) { - if (pCtx->order != pCtx->param[0].i64 || pCtx->preAggVals.dataBlockLoaded == false) { + if (pCtx->order != pCtx->param[0].i64/* || pCtx->preAggVals.dataBlockLoaded == false*/) { return; } @@ -1934,6 +1981,7 @@ static void last_function(SQLFunctionCtx *pCtx) { continue; } } + memcpy(pCtx->pOutput, data, pCtx->inputBytes); TSKEY ts = GET_TS_DATA(pCtx, i); @@ -2013,13 +2061,7 @@ static void last_dist_function(SQLFunctionCtx *pCtx) { return; } - // data block is discard, not loaded, do not need to check it - if (!pCtx->preAggVals.dataBlockLoaded) { - return; - } - int32_t notNullElems = 0; - for (int32_t i = pCtx->size - 1; i >= 0; --i) { char *data = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType)) { @@ -2125,12 +2167,7 @@ static void last_row_finalizer(SQLFunctionCtx *pCtx) { // do nothing at the first stage SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); if (pResInfo->hasResult != DATA_SET_FLAG) { - if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) { - setVardataNull(pCtx->pOutput, pCtx->outputType); - } else { - setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); - } - + setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } @@ -2445,7 +2482,7 @@ static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) { } } -bool topbot_datablock_filter(SQLFunctionCtx *pCtx, int32_t functionId, const char *minval, const char *maxval) { +bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const char *maxval) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); if (pResInfo == NULL) { return true; @@ -2460,7 +2497,7 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, int32_t functionId, const cha tValuePair **pRes = (tValuePair**) pTopBotInfo->res; - if (functionId == TSDB_FUNC_TOP) { + if (pCtx->functionId == TSDB_FUNC_TOP) { switch (pCtx->inputType) { case TSDB_DATA_TYPE_TINYINT: return GET_INT8_VAL(maxval) > pRes[0]->v.i64; @@ -2531,9 +2568,13 @@ static bool top_bottom_function_setup(SQLFunctionCtx *pCtx) { static void top_function(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; - + STopBotInfo *pRes = getTopBotOutputInfo(pCtx); assert(pRes->num >= 0); + + if ((void *)pRes->res[0] != (void *)((char *)pRes + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { + buildTopBotStruct(pRes, pCtx); + } for (int32_t i = 0; i < pCtx->size; ++i) { char *data = GET_INPUT_DATA(pCtx, i); @@ -2609,13 +2650,13 @@ static void bottom_function(SQLFunctionCtx *pCtx) { if ((void *)pRes->res[0] != (void *)((char *)pRes + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { buildTopBotStruct(pRes, pCtx); } - + for (int32_t i = 0; i < pCtx->size; ++i) { char *data = GET_INPUT_DATA(pCtx, i); TSKEY ts = GET_TS_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType)) { - continue; + continue; } notNullElems++; @@ -2648,7 +2689,7 @@ static void bottom_function_f(SQLFunctionCtx *pCtx, int32_t index) { if ((void *)pRes->res[0] != (void *)((char *)pRes + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { buildTopBotStruct(pRes, pCtx); } - + SET_VAL(pCtx, 1, 1); do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64, pData, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); @@ -2729,6 +2770,17 @@ static void percentile_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); SPercentileInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); + if (pCtx->currentStage == REPEAT_SCAN && pInfo->stage == 0) { + // all data are null, set it completed + if (pInfo->numOfElems == 0) { + pResInfo->complete = true; + } else { + pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval); + } + + pInfo->stage += 1; + } + // the first stage, only acquire the min/max value if (pInfo->stage == 0) { if (pCtx->preAggVals.isSet) { @@ -2802,10 +2854,20 @@ static void percentile_function_f(SQLFunctionCtx *pCtx, int32_t index) { } SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SPercentileInfo *pInfo = (SPercentileInfo *)GET_ROWCELL_INTERBUF(pResInfo); - if (pInfo->stage == 0) { + if (pCtx->currentStage == REPEAT_SCAN && pInfo->stage == 0) { + // all data are null, set it completed + if (pInfo->numOfElems == 0) { + pResInfo->complete = true; + } else { + pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval); + } + + pInfo->stage += 1; + } + + if (pInfo->stage == 0) { double v = 0; GET_TYPED_DATA(v, double, pCtx->inputType, pData); @@ -3240,8 +3302,6 @@ static void col_project_function(SQLFunctionCtx *pCtx) { pCtx->inputBytes); } } - - pCtx->pOutput += pCtx->size * pCtx->outputBytes; } static void col_project_function_f(SQLFunctionCtx *pCtx, int32_t index) { @@ -3547,9 +3607,6 @@ static void diff_function(SQLFunctionCtx *pCtx) { int32_t forwardStep = (isFirstBlock) ? notNullElems - 1 : notNullElems; GET_RES_INFO(pCtx)->numOfRes += forwardStep; - - pCtx->pOutput += forwardStep * pCtx->outputBytes; - pCtx->ptsOutputBuf = (char*)pCtx->ptsOutputBuf + forwardStep * TSDB_KEYSIZE; } } @@ -3631,7 +3688,7 @@ char *getArithColumnData(void *param, const char* name, int32_t colId) { } } - assert(index >= 0 && colId >= 0); + assert(index >= 0 /*&& colId >= 0*/); return pSupport->data[index] + pSupport->offset * pSupport->colList[index].bytes; } @@ -3640,7 +3697,6 @@ static void arithmetic_function(SQLFunctionCtx *pCtx) { SArithmeticSupport *sas = (SArithmeticSupport *)pCtx->param[1].pz; arithmeticTreeTraverse(sas->pArithExpr->pExpr, pCtx->size, pCtx->pOutput, sas, pCtx->order, getArithColumnData); - pCtx->pOutput += pCtx->outputBytes * pCtx->size; } static void arithmetic_function_f(SQLFunctionCtx *pCtx, int32_t index) { @@ -4171,50 +4227,88 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { } if (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP) { - *(TSKEY *) pCtx->pOutput = pCtx->startTs; + *(TSKEY *)pCtx->pOutput = pCtx->startTs; + } else if (type == TSDB_FILL_NULL) { + setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); + } else if (type == TSDB_FILL_SET_VALUE) { + tVariantDump(&pCtx->param[1], pCtx->pOutput, pCtx->inputType, true); } else { - if (pCtx->start.key == INT64_MIN) { - assert(pCtx->end.key == INT64_MIN); - return; - } - - if (type == TSDB_FILL_NULL) { - setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); - } else if (type == TSDB_FILL_SET_VALUE) { - tVariantDump(&pCtx->param[1], pCtx->pOutput, pCtx->inputType, true); - } else if (type == TSDB_FILL_PREV) { - if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) { - SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->start.val); - } else { - assignVal(pCtx->pOutput, pCtx->start.ptr, pCtx->outputBytes, pCtx->inputType); + if (pCtx->start.key != INT64_MIN && pCtx->start.key < pCtx->startTs && pCtx->end.key > pCtx->startTs) { + if (type == TSDB_FILL_PREV) { + if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) { + SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->start.val); + } else { + assignVal(pCtx->pOutput, pCtx->start.ptr, pCtx->outputBytes, pCtx->inputType); + } + } else if (type == TSDB_FILL_NEXT) { + if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) { + SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->end.val); + } else { + assignVal(pCtx->pOutput, pCtx->end.ptr, pCtx->outputBytes, pCtx->inputType); + } + } else if (type == TSDB_FILL_LINEAR) { + SPoint point1 = {.key = pCtx->start.key, .val = &pCtx->start.val}; + SPoint point2 = {.key = pCtx->end.key, .val = &pCtx->end.val}; + SPoint point = {.key = pCtx->startTs, .val = pCtx->pOutput}; + + int32_t srcType = pCtx->inputType; + if (IS_NUMERIC_TYPE(srcType)) { // TODO should find the not null data? + if (isNull((char *)&pCtx->start.val, srcType) || isNull((char *)&pCtx->end.val, srcType)) { + setNull(pCtx->pOutput, srcType, pCtx->inputBytes); + } else { + taosGetLinearInterpolationVal(&point, pCtx->outputType, &point1, &point2, TSDB_DATA_TYPE_DOUBLE); + } + } else { + setNull(pCtx->pOutput, srcType, pCtx->inputBytes); + } } - } else if (type == TSDB_FILL_NEXT) { - if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) { - SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->end.val); - } else { - assignVal(pCtx->pOutput, pCtx->end.ptr, pCtx->outputBytes, pCtx->inputType); + } else { + // no data generated yet + if (pCtx->size == 1) { + return; } - } else if (type == TSDB_FILL_LINEAR) { - SPoint point1 = {.key = pCtx->start.key, .val = &pCtx->start.val}; - SPoint point2 = {.key = pCtx->end.key, .val = &pCtx->end.val}; - SPoint point = {.key = pCtx->startTs, .val = pCtx->pOutput}; - - int32_t srcType = pCtx->inputType; - if (IS_NUMERIC_TYPE(srcType)) { // TODO should find the not null data? - if (isNull((char *)&pCtx->start.val, srcType) || isNull((char *)&pCtx->end.val, srcType)) { - setNull(pCtx->pOutput, srcType, pCtx->inputBytes); + + // check the timestamp in input buffer + TSKEY skey = GET_TS_DATA(pCtx, 0); + TSKEY ekey = GET_TS_DATA(pCtx, 1); + + // no data generated yet + if (!(skey < pCtx->startTs && ekey > pCtx->startTs)) { + return; + } + + assert(pCtx->start.key == INT64_MIN && skey < pCtx->startTs && ekey > pCtx->startTs); + + if (type == TSDB_FILL_PREV) { + assignVal(pCtx->pOutput, pCtx->pInput, pCtx->outputBytes, pCtx->inputType); + } else if (type == TSDB_FILL_NEXT) { + char* val = ((char*)pCtx->pInput) + pCtx->inputBytes; + assignVal(pCtx->pOutput, val, pCtx->outputBytes, pCtx->inputType); + } else if (type == TSDB_FILL_LINEAR) { + char *start = GET_INPUT_DATA(pCtx, 0); + char *end = GET_INPUT_DATA(pCtx, 1); + + SPoint point1 = {.key = skey, .val = start}; + SPoint point2 = {.key = ekey, .val = end}; + SPoint point = {.key = pCtx->startTs, .val = pCtx->pOutput}; + + int32_t srcType = pCtx->inputType; + if (IS_NUMERIC_TYPE(srcType)) { // TODO should find the not null data? + if (isNull(start, srcType) || isNull(end, srcType)) { + setNull(pCtx->pOutput, srcType, pCtx->inputBytes); + } else { + taosGetLinearInterpolationVal(&point, pCtx->outputType, &point1, &point2, srcType); + } } else { - taosGetLinearInterpolationVal(&point, pCtx->outputType, &point1, &point2, TSDB_DATA_TYPE_DOUBLE); + setNull(pCtx->pOutput, srcType, pCtx->inputBytes); } - } else { - setNull(pCtx->pOutput, srcType, pCtx->inputBytes); } } } SET_VAL(pCtx, 1, 1); - } + static void interp_function(SQLFunctionCtx *pCtx) { // at this point, the value is existed, return directly if (pCtx->size > 0) { @@ -4289,11 +4383,22 @@ static void ts_comp_finalize(SQLFunctionCtx *pCtx) { STSBuf * pTSbuf = pInfo->pTSBuf; tsBufFlush(pTSbuf); - + qDebug("total timestamp :%"PRId64, pTSbuf->numOfTotal); + + // TODO refactor transfer ownership of current file *(FILE **)pCtx->pOutput = pTSbuf->f; + pResInfo->complete = true; + + // get the file size + struct stat fStat; + if ((fstat(fileno(pTSbuf->f), &fStat) == 0)) { + pResInfo->numOfRes = fStat.st_size; + } + pTSbuf->remainOpen = true; tsBufDestroy(pTSbuf); + doFinalizer(pCtx); } @@ -4637,10 +4742,126 @@ static void sumrate_finalizer(SQLFunctionCtx *pCtx) { doFinalizer(pCtx); } +void blockInfo_func(SQLFunctionCtx* pCtx) { + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + STableBlockDist* pDist = (STableBlockDist*) GET_ROWCELL_INTERBUF(pResInfo); -///////////////////////////////////////////////////////////////////////////////////////////// + int32_t len = *(int32_t*) pCtx->pInput; + blockDistInfoFromBinary((char*)pCtx->pInput + sizeof(int32_t), len, pDist); + pDist->rowSize = (int16_t) pCtx->param[0].i64; + + memcpy(pCtx->pOutput, pCtx->pInput, sizeof(int32_t) + len); + pResInfo->numOfRes = 1; + pResInfo->hasResult = DATA_SET_FLAG; +} +static void mergeTableBlockDist(STableBlockDist* pDist, const STableBlockDist* pSrc) { + assert(pDist != NULL && pSrc != NULL); + pDist->numOfTables += pSrc->numOfTables; + pDist->numOfRowsInMemTable += pSrc->numOfRowsInMemTable; + pDist->numOfFiles += pSrc->numOfFiles; + pDist->totalSize += pSrc->totalSize; + + if (pDist->dataBlockInfos == NULL) { + pDist->dataBlockInfos = taosArrayInit(4, sizeof(SFileBlockInfo)); + } + + taosArrayPushBatch(pDist->dataBlockInfos, pSrc->dataBlockInfos->pData, (int32_t) taosArrayGetSize(pSrc->dataBlockInfos)); +} + +void block_func_merge(SQLFunctionCtx* pCtx) { + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + + STableBlockDist* pDist = (STableBlockDist*) GET_ROWCELL_INTERBUF(pResInfo); + STableBlockDist info = {0}; + + int32_t len = *(int32_t*) pCtx->pInput; + blockDistInfoFromBinary(((char*)pCtx->pInput) + sizeof(int32_t), len, &info); + + mergeTableBlockDist(pDist, &info); +} + +static int32_t doGetPercentile(const SArray* pArray, double rate) { + int32_t len = (int32_t)taosArrayGetSize(pArray); + if (len <= 0) { + return 0; + } + + assert(rate >= 0 && rate <= 1.0); + int idx = (int32_t)((len - 1) * rate); + + return ((SFileBlockInfo *)(taosArrayGet(pArray, idx)))->numOfRows; +} + +static int compareBlockInfo(const void *pLeft, const void *pRight) { + int32_t left = ((SFileBlockInfo *)pLeft)->numOfRows; + int32_t right = ((SFileBlockInfo *)pRight)->numOfRows; + + if (left > right) return 1; + if (left < right) return -1; + return 0; +} + +void generateBlockDistResult(STableBlockDist *pTableBlockDist, char* result) { + if (pTableBlockDist == NULL) { + return; + } + + int64_t min = INT64_MAX, max = INT64_MIN, avg = 0; + SArray* blockInfos= pTableBlockDist->dataBlockInfos; + int64_t totalRows = 0, totalBlocks = taosArrayGetSize(blockInfos); + + for (size_t i = 0; i < taosArrayGetSize(blockInfos); i++) { + SFileBlockInfo *blockInfo = taosArrayGet(blockInfos, i); + int64_t rows = blockInfo->numOfRows; + + min = MIN(min, rows); + max = MAX(max, rows); + totalRows += rows; + } + + avg = totalBlocks > 0 ? (int64_t)(totalRows/totalBlocks) : 0; + taosArraySort(blockInfos, compareBlockInfo); + + uint64_t totalLen = pTableBlockDist->totalSize; + int32_t rowSize = pTableBlockDist->rowSize; + + int sz = sprintf(result + VARSTR_HEADER_SIZE, + "summary: \n\t " + "5th=[%d], 10th=[%d], 20th=[%d], 30th=[%d], 40th=[%d], 50th=[%d]\n\t " + "60th=[%d], 70th=[%d], 80th=[%d], 90th=[%d], 95th=[%d], 99th=[%d]\n\t " + "Min=[%"PRId64"(Rows)] Max=[%"PRId64"(Rows)] Avg=[%"PRId64"(Rows)] Stddev=[%.2f] \n\t " + "Rows=[%"PRId64"], Blocks=[%"PRId64"], Size=[%.3f(Kb)] Comp=[%.2f%%]\n\t " + "RowsInMem=[%d] \n\t SeekHeaderTime=[%d(us)]", + doGetPercentile(blockInfos, 0.05), doGetPercentile(blockInfos, 0.10), + doGetPercentile(blockInfos, 0.20), doGetPercentile(blockInfos, 0.30), + doGetPercentile(blockInfos, 0.40), doGetPercentile(blockInfos, 0.50), + doGetPercentile(blockInfos, 0.60), doGetPercentile(blockInfos, 0.70), + doGetPercentile(blockInfos, 0.80), doGetPercentile(blockInfos, 0.90), + doGetPercentile(blockInfos, 0.95), doGetPercentile(blockInfos, 0.99), + min, max, avg, 0.0, + totalRows, totalBlocks, totalLen/1024.0, (double)(totalLen*100.0)/(rowSize*totalRows), + pTableBlockDist->numOfRowsInMemTable, pTableBlockDist->firstSeekTimeUs); + varDataSetLen(result, sz); + UNUSED(sz); +} + +void blockinfo_func_finalizer(SQLFunctionCtx* pCtx) { + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + STableBlockDist* pDist = (STableBlockDist*) GET_ROWCELL_INTERBUF(pResInfo); + + pDist->rowSize = (int16_t)pCtx->param[0].i64; + generateBlockDistResult(pDist, pCtx->pOutput); + + // cannot set the numOfIteratedElems again since it is set during previous iteration + pResInfo->numOfRes = 1; + pResInfo->hasResult = DATA_SET_FLAG; + + doFinalizer(pCtx); +} + +///////////////////////////////////////////////////////////////////////////////////////////// /* * function compatible list. * tag and ts are not involved in the compatibility check @@ -4659,8 +4880,8 @@ int32_t functionCompatList[] = { 4, -1, -1, 1, 1, 1, 1, 1, 1, -1, // tag, colprj, tagprj, arithmetic, diff, first_dist, last_dist, interp rate irate 1, 1, 1, 1, -1, 1, 1, 5, 1, 1, - // sum_rate, sum_irate, avg_rate, avg_irate - 1, 1, 1, 1, + // sum_rate, sum_irate, avg_rate, avg_irate, tid_tag, blk_info + 1, 1, 1, 1, 6, 7 }; SAggFunctionInfo aAggs[] = {{ @@ -4675,7 +4896,7 @@ SAggFunctionInfo aAggs[] = {{ no_next_step, doFinalizer, count_func_merge, - count_load_data_info, + countRequired, }, { // 1 @@ -4860,7 +5081,7 @@ SAggFunctionInfo aAggs[] = {{ no_next_step, spread_function_finalizer, spread_func_merge, - count_load_data_info, + countRequired, }, { // 14 @@ -4902,7 +5123,7 @@ SAggFunctionInfo aAggs[] = {{ no_next_step, doFinalizer, copy_function, - no_data_info, + noDataRequired, }, { // 17 @@ -4930,7 +5151,7 @@ SAggFunctionInfo aAggs[] = {{ no_next_step, doFinalizer, copy_function, - no_data_info, + noDataRequired, }, { // 19 @@ -4958,7 +5179,7 @@ SAggFunctionInfo aAggs[] = {{ no_next_step, doFinalizer, copy_function, - no_data_info, + noDataRequired, }, { // 21, column project sql function @@ -4986,7 +5207,7 @@ SAggFunctionInfo aAggs[] = {{ no_next_step, doFinalizer, copy_function, - no_data_info, + noDataRequired, }, { // 23 @@ -5159,7 +5380,7 @@ SAggFunctionInfo aAggs[] = {{ }, { // 35 - "tid_tag", // return table id and the corresponding tags for join match and subscribe + "tbid", // return table id and the corresponding tags for join match and subscribe TSDB_FUNC_TID_TAG, TSDB_FUNC_TID_TAG, TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE, @@ -5170,4 +5391,18 @@ SAggFunctionInfo aAggs[] = {{ noop1, noop1, dataBlockRequired, - } }; + }, + { + // 35 + "_block_dist", // return table id and the corresponding tags for join match and subscribe + TSDB_FUNC_BLKINFO, + TSDB_FUNC_BLKINFO, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STABLE, + function_setup, + blockInfo_func, + noop2, + no_next_step, + blockinfo_func_finalizer, + block_func_merge, + dataBlockRequired, + }}; diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index f8119b0d4ad07ea235f8e098149a8703a416427e..dca0e1f46413eec50e8d13350ec4725701f5cb52 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -26,24 +26,22 @@ #include "queryLog.h" #include "tlosertree.h" #include "ttype.h" - -#define MAX_ROWS_PER_RESBUF_PAGE ((1u<<12) - 1) - -/** - * check if the primary column is load by default, otherwise, the program will - * forced to load primary column explicitly. - */ +#include "tscompression.h" #define IS_MASTER_SCAN(runtime) ((runtime)->scanFlag == MASTER_SCAN) #define IS_REVERSE_SCAN(runtime) ((runtime)->scanFlag == REVERSE_SCAN) #define SET_MASTER_SCAN_FLAG(runtime) ((runtime)->scanFlag = MASTER_SCAN) #define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN) -#define GET_QINFO_ADDR(x) ((SQInfo *)((char *)(x)-offsetof(SQInfo, runtimeEnv))) - -#define GET_COL_DATA_POS(query, index, step) ((query)->pos + (index) * (step)) #define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC)) +#define CHECK_IF_QUERY_KILLED(_q) \ + do { \ + if (isQueryKilled((_q)->qinfo)) { \ + longjmp((_q)->env, TSDB_CODE_TSC_QUERY_CANCELLED); \ + } \ + } while (0) + #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} #define TIME_WINDOW_COPY(_dst, _src) do {\ @@ -57,20 +55,10 @@ enum { TS_JOIN_TAG_NOT_EQUALS = 2, }; -typedef struct { - int32_t status; // query status - TSKEY lastKey; // the lastKey value before query executed - STimeWindow w; // whole query time window - int32_t windowIndex; // index of active time window result for interval query - STSCursor cur; -} SQueryStatusInfo; - -typedef struct { - SArray *dataBlockInfos; - int64_t firstSeekTimeUs; - int64_t numOfRowsInMemTable; - char *result; -} STableBlockDist; +typedef enum SResultTsInterpType { + RESULT_ROW_START_INTERP = 1, + RESULT_ROW_END_INTERP = 2, +} SResultTsInterpType; #if 0 static UNUSED_FUNC void *u_malloc (size_t __size) { @@ -110,8 +98,6 @@ static UNUSED_FUNC void* u_realloc(void* p, size_t __size) { #define GET_NUM_OF_TABLEGROUP(q) taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList) #define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0) -static void finalizeQueryResult(SQueryRuntimeEnv *pRuntimeEnv); - int32_t getMaximumIdleDurationSec() { return tsShellActivityTimer * 2; } @@ -153,84 +139,122 @@ static void getNextTimeWindow(SQuery* pQuery, STimeWindow* tw) { tw->ekey -= 1; } -static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult); -static void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult); +static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes); +static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, + int32_t numOfCols, int32_t* rowCellInfoOffset); + +void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowCellInfoOffset); static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId); -static void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void* inputData, TSKEY *tsCol, SDataBlockInfo* pBlockInfo, - SDataStatis *pStatis, SExprInfo* pExprInfo); +static void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex); -static void initCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv); static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo); -static void resetDefaultResInfoOutputBuf(SQueryRuntimeEnv *pRuntimeEnv); static bool hasMainOutput(SQuery *pQuery); -static int32_t setTimestampListJoinInfo(SQInfo *pQInfo, STableQueryInfo *pTableQueryInfo); +static int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo); static void releaseQueryBuf(size_t numOfTables); static int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order); -static void doRowwiseTimeWindowInterpolation(SQueryRuntimeEnv* pRuntimeEnv, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type); static STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win); -static STableIdInfo createTableIdInfo(SQuery* pQuery); - -bool doFilterData(SQuery *pQuery, int32_t elemPos) { - for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) { - SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k]; - - char *pElem = (char*)pFilterInfo->pData + pFilterInfo->info.bytes * elemPos; +static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo); + +static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream); + +static int32_t getNumOfScanTimes(SQuery* pQuery); +static bool isFixedOutputQuery(SQuery* pQuery); + +static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime); +static SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime); +static SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv); + +static SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream); +static SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream); +static SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput); +static SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv); + +static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput); +static void destroySFillOperatorInfo(void* param, int32_t numOfOutput); +static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput); +static void destroyArithOperatorInfo(void* param, int32_t numOfOutput); +static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput); +static void destroyOperatorInfo(SOperatorInfo* pOperator); + +static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock); + +static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock); +static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SGroupbyOperatorInfo *pInfo, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex); + +static void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size); +static void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win); +static bool isPointInterpoQuery(SQuery *pQuery); +static void setResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo); +static void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable); +static void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr); +static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, + SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput, + int32_t groupIndex); + +// setup the output buffer for each operator +static SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows) { + const static int32_t minSize = 8; + + SSDataBlock *res = calloc(1, sizeof(SSDataBlock)); + res->info.numOfCols = numOfOutput; + + res->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData)); + for (int32_t i = 0; i < numOfOutput; ++i) { + SColumnInfoData idata = {{0}}; + idata.info.type = pExpr[i].type; + idata.info.bytes = pExpr[i].bytes; + idata.info.colId = pExpr[i].base.resColId; - bool qualified = false; - for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) { - SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j]; + idata.pData = calloc(1, MAX(idata.info.bytes * numOfRows, minSize)); // at least to hold a pointer on x64 platform + taosArrayPush(res->pDataBlock, &idata); + } - bool isnull = isNull(pElem, pFilterInfo->info.type); - if (isnull) { - if (pFilterElem->fp == isNullOperator) { - qualified = true; - break; - } else { - continue; - } - } else { - if (pFilterElem->fp == notNullOperator) { - qualified = true; - break; - } else if (pFilterElem->fp == isNullOperator) { - continue; - } - } + return res; +} - if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo->info.type)) { - qualified = true; - break; - } - } +static void* destroyOutputBuf(SSDataBlock* pBlock) { + if (pBlock == NULL) { + return NULL; + } - if (!qualified) { - return false; - } + int32_t numOfOutput = pBlock->info.numOfCols; + for(int32_t i = 0; i < numOfOutput; ++i) { + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i); + tfree(pColInfoData->pData); } - return true; + taosArrayDestroy(pBlock->pDataBlock); + tfree(pBlock->pBlockStatis); + tfree(pBlock); + return NULL; } -int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) { +int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) { SQuery *pQuery = pRuntimeEnv->pQuery; bool hasMainFunction = hasMainOutput(pQuery); - int64_t maxOutput = 0; - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int32_t functionId = pQuery->pExpr1[j].base.functionId; + int32_t maxOutput = 0; + for (int32_t j = 0; j < numOfOutput; ++j) { + int32_t id = pCtx[j].functionId; /* * ts, tag, tagprj function can not decide the output number of current query * the number of output result is decided by main output */ - if (hasMainFunction && - (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ)) { + if (hasMainFunction && (id == TSDB_FUNC_TS || id == TSDB_FUNC_TAG || id == TSDB_FUNC_TAGPRJ)) { continue; } - SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]); + SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]); if (pResInfo != NULL && maxOutput < pResInfo->numOfRes) { maxOutput = pResInfo->numOfRes; } @@ -240,27 +264,14 @@ int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) { return maxOutput; } -/* - * the value of number of result needs to be update due to offset value upated. - */ -void updateNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfRes) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]); - - int16_t functionId = pRuntimeEnv->pCtx[j].functionId; - if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || - functionId == TSDB_FUNC_TS_DUMMY) { - continue; - } - - assert(pResInfo->numOfRes > numOfRes); - pResInfo->numOfRes = numOfRes; +static void clearNumOfRes(SQLFunctionCtx* pCtx, int32_t numOfOutput) { + for (int32_t j = 0; j < numOfOutput; ++j) { + SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]); + pResInfo->numOfRes = 0; } } -bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) { +static bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) { if (pGroupbyExpr == NULL || pGroupbyExpr->numOfGroupCols == 0) { return false; } @@ -280,7 +291,7 @@ bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) { return false; } -bool isStabledev(SQuery* pQuery) { +static bool isStabledev(SQuery* pQuery) { for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t functId = pQuery->pExpr1[i].base.functionId; if (functId == TSDB_FUNC_STDDEV_DST) { @@ -291,36 +302,12 @@ bool isStabledev(SQuery* pQuery) { return false; } -int16_t getGroupbyColumnType(SQuery *pQuery, SSqlGroupbyExpr *pGroupbyExpr) { - assert(pGroupbyExpr != NULL); - - int32_t colId = -2; - int16_t type = TSDB_DATA_TYPE_NULL; - - for (int32_t i = 0; i < pGroupbyExpr->numOfGroupCols; ++i) { - SColIndex *pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, i); - if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) { - colId = pColIndex->colId; - break; - } - } - - for (int32_t i = 0; i < pQuery->numOfCols; ++i) { - if (colId == pQuery->colList[i].colId) { - type = pQuery->colList[i].type; - break; - } - } - - return type; -} - -static bool isSelectivityWithTagsQuery(SQuery *pQuery) { +static bool isSelectivityWithTagsQuery(SQLFunctionCtx *pCtx, int32_t numOfOutput) { bool hasTags = false; int32_t numOfSelectivity = 0; - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - int32_t functId = pQuery->pExpr1[i].base.functionId; + for (int32_t i = 0; i < numOfOutput; ++i) { + int32_t functId = pCtx[i].functionId; if (functId == TSDB_FUNC_TAG_DUMMY || functId == TSDB_FUNC_TS_DUMMY) { hasTags = true; continue; @@ -331,11 +318,7 @@ static bool isSelectivityWithTagsQuery(SQuery *pQuery) { } } - if (numOfSelectivity > 0 && hasTags) { - return true; - } - - return false; + return (numOfSelectivity > 0 && hasTags); } static bool isProjQuery(SQuery *pQuery) { @@ -351,20 +334,6 @@ static bool isProjQuery(SQuery *pQuery) { static bool isTsCompQuery(SQuery *pQuery) { return pQuery->pExpr1[0].base.functionId == TSDB_FUNC_TS_COMP; } -static bool limitOperator(SQuery* pQuery, void* qinfo) { - if ((pQuery->limit.limit > 0) && (pQuery->rec.total + pQuery->rec.rows > pQuery->limit.limit)) { - pQuery->rec.rows = pQuery->limit.limit - pQuery->rec.total; - - qDebug("QInfo:%p discard remain data due to result limitation, limit:%"PRId64", current return:%" PRId64 ", total:%"PRId64, - qinfo, pQuery->limit.limit, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows); - assert(pQuery->rec.rows >= 0); - setQueryStatus(pQuery, QUERY_COMPLETED); - return true; - } - - return false; -} - static bool isTopBottomQuery(SQuery *pQuery) { for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t functionId = pQuery->pExpr1[i].base.functionId; @@ -409,33 +378,44 @@ static bool hasTagValOutput(SQuery* pQuery) { return false; } -/** - * @param pQuery - * @param col - * @param pDataBlockInfo - * @param pStatis - * @param pColStatis - * @return - */ -static bool hasNullValue(SColIndex* pColIndex, SDataStatis *pStatis, SDataStatis **pColStatis) { - if (pStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) { - *pColStatis = &pStatis[pColIndex->colIndex]; - assert((*pColStatis)->colId == pColIndex->colId); - } else { - *pColStatis = NULL; - } - +static bool hasNullRv(SColIndex* pColIndex, SDataStatis *pStatis) { if (TSDB_COL_IS_TAG(pColIndex->flag) || TSDB_COL_IS_UD_COL(pColIndex->flag) || pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { return false; } - if ((*pColStatis) != NULL && (*pColStatis)->numOfNull == 0) { + if (pStatis != NULL && pStatis->numOfNull == 0) { return false; } return true; } +static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, SQueryRuntimeEnv* pRuntimeEnv) { + // more than the capacity, reallocate the resources + if (pResultRowInfo->size < pResultRowInfo->capacity) { + return; + } + + int64_t newCapacity = 0; + if (pResultRowInfo->capacity > 10000) { + newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25); + } else { + newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5); + } + + char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES)); + if (t == NULL) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + pResultRowInfo->pResult = (SResultRow **)t; + + int32_t inc = (int32_t)newCapacity - pResultRowInfo->capacity; + memset(&pResultRowInfo->pResult[pResultRowInfo->capacity], 0, POINTER_BYTES * inc); + + pResultRowInfo->capacity = (int32_t)newCapacity; +} + static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData, int16_t bytes, bool masterscan, uint64_t uid) { bool existed = false; @@ -466,28 +446,7 @@ static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SRes } if (!existed) { - // TODO refactor - // more than the capacity, reallocate the resources - if (pResultRowInfo->size >= pResultRowInfo->capacity) { - int64_t newCapacity = 0; - if (pResultRowInfo->capacity > 10000) { - newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25); - } else { - newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5); - } - - char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES)); - if (t == NULL) { - longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - pResultRowInfo->pResult = (SResultRow **)t; - - int32_t inc = (int32_t)newCapacity - pResultRowInfo->capacity; - memset(&pResultRowInfo->pResult[pResultRowInfo->capacity], 0, POINTER_BYTES * inc); - - pResultRowInfo->capacity = (int32_t)newCapacity; - } + prepareResultListBuffer(pResultRowInfo, pRuntimeEnv); SResultRow *pResult = NULL; @@ -517,19 +476,30 @@ static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SRes } // get the correct time window according to the handled timestamp -static STimeWindow getActiveTimeWindow(SResultRowInfo *pWindowResInfo, int64_t ts, SQuery *pQuery) { +static STimeWindow getActiveTimeWindow(SResultRowInfo * pResultRowInfo, int64_t ts, SQuery *pQuery) { STimeWindow w = {0}; - if (pWindowResInfo->curIndex == -1) { // the first window, from the previous stored value - w.skey = pWindowResInfo->prevSKey; + if (pResultRowInfo->curIndex == -1) { // the first window, from the previous stored value + if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) { + if (QUERY_IS_ASC_QUERY(pQuery)) { + getAlignQueryTimeWindow(pQuery, ts, ts, pQuery->window.ekey, &w); + } else { // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp + getAlignQueryTimeWindow(pQuery, ts, pQuery->window.ekey, ts, &w); + } + + pResultRowInfo->prevSKey = w.skey; + } else { + w.skey = pResultRowInfo->prevSKey; + } + if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; } else { w.ekey = w.skey + pQuery->interval.interval - 1; } } else { - int32_t slot = curTimeWindowIndex(pWindowResInfo); - SResultRow* pWindowRes = getResultRow(pWindowResInfo, slot); + int32_t slot = curTimeWindowIndex(pResultRowInfo); + SResultRow* pWindowRes = getResultRow(pResultRowInfo, slot); w = pWindowRes->win; } @@ -565,8 +535,8 @@ static STimeWindow getActiveTimeWindow(SResultRowInfo *pWindowResInfo, int64_t t return w; } -static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf *pResultBuf, int32_t tid, - int32_t numOfRowsPerPage) { +// a new buffer page for each table. Needs to opt this design +static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf *pResultBuf, int32_t tid, uint32_t size) { if (pWindowRes->pageId != -1) { return 0; } @@ -584,7 +554,7 @@ static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf pData = getResBufPage(pResultBuf, pi->pageId); pageId = pi->pageId; - if (pData->num >= numOfRowsPerPage) { + if (pData->num + size > pResultBuf->pageSize) { // release current page first, and prepare the next one releaseResBufPageInfo(pResultBuf, pi); pData = getNewDataBuf(pResultBuf, tid, &pageId); @@ -601,8 +571,9 @@ static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf // set the number of rows in current disk page if (pWindowRes->pageId == -1) { // not allocated yet, allocate new buffer pWindowRes->pageId = pageId; - pWindowRes->rowId = (int32_t)(pData->num++); + pWindowRes->offset = (int32_t)pData->num; + pData->num += size; assert(pWindowRes->pageId >= 0); } @@ -610,7 +581,8 @@ static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf } static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win, - bool masterscan, SResultRow **pResult, int64_t groupId) { + bool masterscan, SResultRow **pResult, int64_t groupId, SQLFunctionCtx* pCtx, + int32_t numOfOutput, int32_t* rowCellInfoOffset) { assert(win->skey <= win->ekey); SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf; @@ -622,7 +594,7 @@ static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRow // not assign result buffer yet, add new result buffer if (pResultRow->pageId == -1) { - int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->numOfRowsPerPage); + int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQuery->intermediateResultRowSize); if (ret != TSDB_CODE_SUCCESS) { return -1; } @@ -631,21 +603,11 @@ static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRow // set time window for current result pResultRow->win = (*win); *pResult = pResultRow; - setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow); + setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset); return TSDB_CODE_SUCCESS; } -static bool getResultRowStatus(SResultRowInfo *pWindowResInfo, int32_t slot) { - assert(slot >= 0 && slot < pWindowResInfo->size); - return pWindowResInfo->pResult[slot]->closed; -} - -typedef enum SResultTsInterpType { - RESULT_ROW_START_INTERP = 1, - RESULT_ROW_END_INTERP = 2, -} SResultTsInterpType; - static void setResultRowInterpo(SResultRow* pResult, SResultTsInterpType type) { assert(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP)); if (type == RESULT_ROW_START_INTERP) { @@ -743,13 +705,14 @@ static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, } } -static void updateResultRowIndex(SResultRowInfo* pResultRowInfo, STableQueryInfo* pTableQueryInfo, bool ascQuery, bool timeWindowInterpo) { - if ((pTableQueryInfo->lastKey > pTableQueryInfo->win.ekey && ascQuery) || (pTableQueryInfo->lastKey < pTableQueryInfo->win.ekey && (!ascQuery))) { +static void updateResultRowInfoActiveIndex(SResultRowInfo* pResultRowInfo, SQuery* pQuery, TSKEY lastKey) { + bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); + if ((lastKey > pQuery->window.ekey && ascQuery) || (lastKey < pQuery->window.ekey && (!ascQuery))) { closeAllResultRows(pResultRowInfo); pResultRowInfo->curIndex = pResultRowInfo->size - 1; } else { - int32_t step = ascQuery? 1:-1; - doUpdateResultRowIndex(pResultRowInfo, pTableQueryInfo->lastKey - step, ascQuery, timeWindowInterpo); + int32_t step = ascQuery ? 1 : -1; + doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQuery->timeWindowInterpo); } } @@ -793,31 +756,27 @@ static int32_t getNumOfRowsInTimeWindow(SQuery *pQuery, SDataBlockInfo *pDataBlo return num; } -static char *getDataBlock(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas, int32_t col, int32_t size, SArray *pDataBlock); - -static void doBlockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pWin, int32_t offset, - int32_t forwardStep, TSKEY *tsCol, int32_t numOfTotal, SArray *pDataBlock) { - SQuery * pQuery = pRuntimeEnv->pQuery; - SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx; - +static void doApplyFunctions(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, STimeWindow* pWin, int32_t offset, + int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput) { + SQuery *pQuery = pRuntimeEnv->pQuery; bool hasPrev = pCtx[0].preAggVals.isSet; - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { + for (int32_t k = 0; k < numOfOutput; ++k) { pCtx[k].size = forwardStep; pCtx[k].startTs = pWin->skey; - char *dataBlock = getDataBlock(pRuntimeEnv, &pRuntimeEnv->sasArray[k], k, numOfTotal, pDataBlock); + char* start = pCtx[k].pInput; int32_t pos = (QUERY_IS_ASC_QUERY(pQuery)) ? offset : offset - (forwardStep - 1); - if (dataBlock != NULL) { - pCtx[k].pInput = (char *)dataBlock + pos * pCtx[k].inputBytes; + if (pCtx[k].pInput != NULL) { + pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes; } if (tsCol != NULL) { pCtx[k].ptsList = &tsCol[pos]; } - int32_t functionId = pQuery->pExpr1[k].base.functionId; + int32_t functionId = pCtx[k].functionId; // not a whole block involved in query processing, statistics data can not be used // NOTE: the original value of isSet have been changed here @@ -831,27 +790,13 @@ static void doBlockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow // restore it pCtx[k].preAggVals.isSet = hasPrev; + pCtx[k].pInput = start; } } -static void doRowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pWin, int32_t offset) { - SQuery *pQuery = pRuntimeEnv->pQuery; - SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx; - - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - pCtx[k].startTs = pWin->skey; - - int32_t functionId = pQuery->pExpr1[k].base.functionId; - if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) { - aAggs[functionId].xFunctionF(&pCtx[k], offset); - } - } -} -static int32_t getNextQualifiedWindow(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo, +static int32_t getNextQualifiedWindow(SQuery* pQuery, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo, TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) { - SQuery *pQuery = pRuntimeEnv->pQuery; - getNextTimeWindow(pQuery, pNext); // next time window is not in current block @@ -941,126 +886,251 @@ static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) return ekey; } -//todo binary search -static void* getDataBlockImpl(SArray* pDataBlock, int32_t colId) { - int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); - - for (int32_t i = 0; i < numOfCols; ++i) { - SColumnInfoData *p = taosArrayGet(pDataBlock, i); - if (colId == p->info.colId) { - return p->pData; +static void setNotInterpoWindowKey(SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t type) { + if (type == RESULT_ROW_START_INTERP) { + for (int32_t k = 0; k < numOfOutput; ++k) { + pCtx[k].start.key = INT64_MIN; + } + } else { + for (int32_t k = 0; k < numOfOutput; ++k) { + pCtx[k].end.key = INT64_MIN; } } - - return NULL; } -// todo refactor -static char *getDataBlock(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas, int32_t col, int32_t size, SArray *pDataBlock) { +// window start key interpolation + + +static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock, + int32_t rowIndex) { if (pDataBlock == NULL) { - return NULL; + return; } - char *dataBlock = NULL; - SQuery *pQuery = pRuntimeEnv->pQuery; + SQuery* pQuery = pRuntimeEnv->pQuery; + for (int32_t k = 0; k < pQuery->numOfCols; ++k) { + SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, k); + memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes); + } +} - int32_t functionId = pQuery->pExpr1[col].base.functionId; - if (functionId == TSDB_FUNC_ARITHM) { - sas->pArithExpr = &pQuery->pExpr1[col]; - sas->offset = (QUERY_IS_ASC_QUERY(pQuery))? pQuery->pos : pQuery->pos - (size - 1); - sas->colList = pQuery->colList; - sas->numOfCols = pQuery->numOfCols; - - // here the pQuery->colList and sas->colList are identical - int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); - for (int32_t i = 0; i < pQuery->numOfCols; ++i) { - SColumnInfo *pColMsg = &pQuery->colList[i]; - - dataBlock = NULL; - for (int32_t k = 0; k < numOfCols; ++k) { //todo refactor - SColumnInfoData *p = taosArrayGet(pDataBlock, k); - if (pColMsg->colId == p->info.colId) { - dataBlock = p->pData; - break; - } - } +static TSKEY getStartTsKey(SQuery* pQuery, STimeWindow* win, const TSKEY* tsCols, int32_t rows) { + TSKEY ts = TSKEY_INITIAL_VAL; + + bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); + if (tsCols == NULL) { + ts = ascQuery? win->skey : win->ekey; + } else { + int32_t offset = ascQuery? 0:rows-1; + ts = tsCols[offset]; + } + + return ts; +} + +static void setArithParams(SArithmeticSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) { + sas->numOfCols = (int32_t) pSDataBlock->info.numOfCols; + sas->pArithExpr = pExprInfo; + + sas->colList = calloc(1, pSDataBlock->info.numOfCols*sizeof(SColumnInfo)); + for(int32_t i = 0; i < sas->numOfCols; ++i) { + SColumnInfoData* pColData = taosArrayGet(pSDataBlock->pDataBlock, i); + sas->colList[i] = pColData->info; + } + + sas->data = calloc(sas->numOfCols, POINTER_BYTES); + + // set the input column data + for (int32_t f = 0; f < pSDataBlock->info.numOfCols; ++f) { + SColumnInfoData *pColumnInfoData = taosArrayGet(pSDataBlock->pDataBlock, f); + sas->data[f] = pColumnInfoData->pData; + } +} + +static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order); +static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { + for (int32_t i = 0; i < pOperator->numOfOutput; ++i) { + pCtx[i].order = order; + pCtx[i].size = pBlock->info.rows; + pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag; + + setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo); + } +} - assert(dataBlock != NULL); - sas->data[i] = dataBlock; // start from the offset +static void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { + if (pCtx[0].functionId == TSDB_FUNC_ARITHM) { + SArithmeticSupport* pSupport = (SArithmeticSupport*) pCtx[0].param[1].pz; + if (pSupport->colList == NULL) { + doSetInputDataBlock(pOperator, pCtx, pBlock, order); + } else { + doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); + } + } else { + if (pCtx[0].pInput == NULL && pBlock->pDataBlock != NULL) { + doSetInputDataBlock(pOperator, pCtx, pBlock, order); + } else { + doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); } + } +} - } else { // other type of query function - SColIndex *pCol = &pQuery->pExpr1[col].base.colInfo; - if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) { - SColIndex* pColIndex = &pQuery->pExpr1[col].base.colInfo; - SColumnInfoData *p = taosArrayGet(pDataBlock, pColIndex->colIndex); - assert(p->info.colId == pColIndex->colId); +static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { + for (int32_t i = 0; i < pOperator->numOfOutput; ++i) { + pCtx[i].order = order; + pCtx[i].size = pBlock->info.rows; + pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag; - dataBlock = p->pData; + setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo); + + if (pCtx[i].functionId == TSDB_FUNC_ARITHM) { + setArithParams((SArithmeticSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock); } else { - dataBlock = NULL; + SColIndex* pCol = &pOperator->pExpr[i].base.colInfo; + if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || pCol->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) { + SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo; + SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex); + + // in case of the block distribution query, the inputBytes is not a constant value. + pCtx[i].pInput = p->pData; + assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type);// && pCtx[i].inputBytes == p->info.bytes); + + uint32_t status = aAggs[pCtx[i].functionId].status; + if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) { + SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); + pCtx[i].ptsList = (int64_t*) tsInfo->pData; + } + } + } + } +} + +static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) { + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + + for (int32_t k = 0; k < pOperator->numOfOutput; ++k) { + int32_t functionId = pCtx[k].functionId; + if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) { + pCtx[k].startTs = startTs;// this can be set during create the struct + aAggs[functionId].xFunction(&pCtx[k]); } } +} + +static void arithmeticApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t numOfOutput) { + SQuery *pQuery = pRuntimeEnv->pQuery; - return dataBlock; + for (int32_t k = 0; k < numOfOutput; ++k) { + pCtx[k].startTs = pQuery->window.skey; + aAggs[pCtx[k].functionId].xFunction(&pCtx[k]); + } } -static void setNotInterpoWindowKey(SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t type) { - if (type == RESULT_ROW_START_INTERP) { - for (int32_t k = 0; k < numOfOutput; ++k) { +void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, SArray* pDataBlock, TSKEY prevTs, + int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type) { + SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv; + SExprInfo* pExpr = pOperator->pExpr; + + SQLFunctionCtx* pCtx = pInfo->pCtx; + + for (int32_t k = 0; k < pOperator->numOfOutput; ++k) { + int32_t functionId = pCtx[k].functionId; + if (functionId != TSDB_FUNC_TWA && functionId != TSDB_FUNC_INTERP) { pCtx[k].start.key = INT64_MIN; + continue; } - } else { - for (int32_t k = 0; k < numOfOutput; ++k) { - pCtx[k].end.key = INT64_MIN; + + SColIndex * pColIndex = &pExpr[k].base.colInfo; + int16_t index = pColIndex->colIndex; + SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, index); + + assert(pColInfo->info.colId == pColIndex->colId && curTs != windowKey); + double v1 = 0, v2 = 0, v = 0; + + if (prevRowIndex == -1) { + GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pRuntimeEnv->prevRow[index]); + } else { + GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pColInfo->pData + prevRowIndex * pColInfo->info.bytes); + } + + GET_TYPED_DATA(v2, double, pColInfo->info.type, (char *)pColInfo->pData + curRowIndex * pColInfo->info.bytes); + + if (functionId == TSDB_FUNC_INTERP) { + if (type == RESULT_ROW_START_INTERP) { + pCtx[k].start.key = prevTs; + pCtx[k].start.val = v1; + + pCtx[k].end.key = curTs; + pCtx[k].end.val = v2; + } + } else if (functionId == TSDB_FUNC_TWA) { + SPoint point1 = (SPoint){.key = prevTs, .val = &v1}; + SPoint point2 = (SPoint){.key = curTs, .val = &v2}; + SPoint point = (SPoint){.key = windowKey, .val = &v }; + + taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE); + + if (type == RESULT_ROW_START_INTERP) { + pCtx[k].start.key = point.key; + pCtx[k].start.val = v; + } else { + pCtx[k].end.key = point.key; + pCtx[k].end.val = v; + } } } } -// window start key interpolation -static bool setTimeWindowInterpolationStartTs(SQueryRuntimeEnv* pRuntimeEnv, int32_t pos, int32_t numOfRows, - SArray* pDataBlock, TSKEY* tsCols, STimeWindow* win, int16_t type) { +static bool setTimeWindowInterpolationStartTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx, int32_t pos, + int32_t numOfRows, SArray* pDataBlock, const TSKEY* tsCols, STimeWindow* win) { + SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv; SQuery* pQuery = pRuntimeEnv->pQuery; + bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); + TSKEY curTs = tsCols[pos]; TSKEY lastTs = *(TSKEY *) pRuntimeEnv->prevRow[0]; // lastTs == INT64_MIN and pos == 0 means this is the first time window, interpolation is not needed. // start exactly from this point, no need to do interpolation - TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->skey:win->ekey; + TSKEY key = ascQuery? win->skey:win->ekey; if (key == curTs) { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); + setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP); return true; } - if (lastTs == INT64_MIN && ((pos == 0 && QUERY_IS_ASC_QUERY(pQuery)) || (pos == (numOfRows - 1) && !QUERY_IS_ASC_QUERY(pQuery)))) { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); + if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) { + setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP); return true; } int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - TSKEY prevTs = ((pos == 0 && QUERY_IS_ASC_QUERY(pQuery)) || (pos == (numOfRows - 1) && !QUERY_IS_ASC_QUERY(pQuery)))? - lastTs:tsCols[pos - step]; + TSKEY prevTs = ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))? lastTs:tsCols[pos - step]; - doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, prevTs, pos - step, curTs, pos, key, RESULT_ROW_START_INTERP); + doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos, + key, RESULT_ROW_START_INTERP); return true; } -static bool setTimeWindowInterpolationEndTs(SQueryRuntimeEnv* pRuntimeEnv, int32_t endRowIndex, SArray* pDataBlock, TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) { +static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx, + int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) { + SQueryRuntimeEnv *pRuntimeEnv = pOperatorInfo->pRuntimeEnv; SQuery* pQuery = pRuntimeEnv->pQuery; + int32_t numOfOutput = pOperatorInfo->numOfOutput; + TSKEY actualEndKey = tsCols[endRowIndex]; TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->ekey:win->skey; // not ended in current data block, do not invoke interpolation if ((key > blockEkey && QUERY_IS_ASC_QUERY(pQuery)) || (key < blockEkey && !QUERY_IS_ASC_QUERY(pQuery))) { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP); + setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP); return false; } // there is actual end point of current time window, no interpolation need if (key == actualEndKey) { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP); + setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP); return true; } @@ -1069,61 +1139,35 @@ static bool setTimeWindowInterpolationEndTs(SQueryRuntimeEnv* pRuntimeEnv, int32 assert(nextRowIndex >= 0); TSKEY nextKey = tsCols[nextRowIndex]; - doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, actualEndKey, endRowIndex, nextKey, nextRowIndex, key, RESULT_ROW_END_INTERP); + doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey, + nextRowIndex, key, RESULT_ROW_END_INTERP); return true; } -static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock, - int32_t rowIndex) { - if (pDataBlock == NULL) { - return; - } - +static void doWindowBorderInterpolation(SOperatorInfo* pOperatorInfo, SSDataBlock* pBlock, SQLFunctionCtx* pCtx, + SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardStep) { + SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv; SQuery* pQuery = pRuntimeEnv->pQuery; - for (int32_t k = 0; k < pQuery->numOfCols; ++k) { - SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, k); - memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes); + if (!pQuery->timeWindowInterpo) { + return; } -} -static TSKEY getStartTsKey(SQuery* pQuery, SDataBlockInfo* pDataBlockInfo, TSKEY* tsCols, int32_t step) { - TSKEY ts = TSKEY_INITIAL_VAL; + assert(pBlock != NULL); + int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - if (tsCols == NULL) { - ts = QUERY_IS_ASC_QUERY(pQuery) ? pDataBlockInfo->window.skey : pDataBlockInfo->window.ekey; - } else { - int32_t offset = GET_COL_DATA_POS(pQuery, 0, step); - ts = tsCols[offset]; - } - - return ts; -} - -static void doWindowBorderInterpolation(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray *pDataBlock, - SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardStep) { - if (!pRuntimeEnv->timeWindowInterpo) { - return; - } - - assert(pDataBlock != NULL); - - SQuery* pQuery = pRuntimeEnv->pQuery; - int32_t fillType = pQuery->fillType; - - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - - SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, 0); + SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, 0); TSKEY *tsCols = (TSKEY *)(pColInfo->pData); bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP); - if (!done) { + if (!done) { // it is not interpolated, now start to generated the interpolated value int32_t startRowIndex = startPos; - bool interp = setTimeWindowInterpolationStartTs(pRuntimeEnv, startRowIndex, pDataBlockInfo->rows, pDataBlock, tsCols, win, fillType); + bool interp = setTimeWindowInterpolationStartTs(pOperatorInfo, pCtx, startRowIndex, pBlock->info.rows, pBlock->pDataBlock, + tsCols, win); if (interp) { setResultRowInterpo(pResult, RESULT_ROW_START_INTERP); } } else { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); + setNotInterpoWindowKey(pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); } // point interpolation does not require the end key time window interpolation. @@ -1136,157 +1180,174 @@ static void doWindowBorderInterpolation(SQueryRuntimeEnv* pRuntimeEnv, SDataBloc if (!done) { int32_t endRowIndex = startPos + (forwardStep - 1) * step; - TSKEY endKey = QUERY_IS_ASC_QUERY(pQuery)? pDataBlockInfo->window.ekey:pDataBlockInfo->window.skey; - bool interp = setTimeWindowInterpolationEndTs(pRuntimeEnv, endRowIndex, pDataBlock, tsCols, endKey, win); + TSKEY endKey = QUERY_IS_ASC_QUERY(pQuery)? pBlock->info.window.ekey:pBlock->info.window.skey; + bool interp = setTimeWindowInterpolationEndTs(pOperatorInfo, pCtx, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win); if (interp) { setResultRowInterpo(pResult, RESULT_ROW_END_INTERP); } } else { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP); + setNotInterpoWindowKey(pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP); } } -/** - * todo set the last value for pQueryTableInfo as in rowwiseapplyfunctions - * @param pRuntimeEnv - * @param forwardStep - * @param tsCols - * @param pFields - * @param isDiskFileBlock - * @return the incremental number of output value, so it maybe 0 for fixed number of query, - * such as count/min/max etc. - */ -static void blockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pStatis, SDataBlockInfo *pDataBlockInfo, - SResultRowInfo *pWindowResInfo, __block_search_fn_t searchFn, SArray *pDataBlock) { - SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx; - bool masterScan = IS_MASTER_SCAN(pRuntimeEnv); - - SQuery *pQuery = pRuntimeEnv->pQuery; - int64_t groupId = pQuery->current->groupIndex; - - TSKEY *tsCols = NULL; - if (pDataBlock != NULL) { - SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, 0); - tsCols = (TSKEY *)(pColInfo->pData); - } +static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pSDataBlock, int32_t groupId) { + STableIntervalOperatorInfo* pInfo = (STableIntervalOperatorInfo*) pOperatorInfo->info; - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - char *dataBlock = getDataBlock(pRuntimeEnv, &pRuntimeEnv->sasArray[k], k, pDataBlockInfo->rows, pDataBlock); - setExecParams(pQuery, &pCtx[k], dataBlock, tsCols, pDataBlockInfo, pStatis, &pQuery->pExpr1[k]); - } + SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv; + int32_t numOfOutput = pOperatorInfo->numOfOutput; + SQuery* pQuery = pRuntimeEnv->pQuery; int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - int32_t prevIndex = curTimeWindowIndex(pWindowResInfo); - - TSKEY ts = getStartTsKey(pQuery, pDataBlockInfo, tsCols, step); - STimeWindow win = getActiveTimeWindow(pWindowResInfo, ts, pQuery); + bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); - SResultRow* pResult = NULL; - int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId); - if (ret != TSDB_CODE_SUCCESS || pResult == NULL) { - goto _end; - } + int32_t prevIndex = curTimeWindowIndex(pResultRowInfo); - int32_t forwardStep = 0; - int32_t startPos = pQuery->pos; + TSKEY* tsCols = NULL; + if (pSDataBlock->pDataBlock != NULL) { + SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0); + tsCols = (int64_t*) pColDataInfo->pData; + assert(tsCols[0] == pSDataBlock->info.window.skey && + tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey); + } - TSKEY ekey = reviseWindowEkey(pQuery, &win); - forwardStep = getNumOfRowsInTimeWindow(pQuery, pDataBlockInfo, tsCols, pQuery->pos, ekey, searchFn, true); + int32_t startPos = ascQuery? 0 : (pSDataBlock->info.rows - 1); + TSKEY ts = getStartTsKey(pQuery, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows); - // prev time window not interpolation yet. - int32_t curIndex = curTimeWindowIndex(pWindowResInfo); - if (prevIndex != -1 && prevIndex < curIndex && pRuntimeEnv->timeWindowInterpo) { - for(int32_t j = prevIndex; j < curIndex; ++j) { // previous time window may be all closed already. - SResultRow *pRes = pWindowResInfo->pResult[j]; - if (pRes->closed) { - assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) && resultRowInterpolated(pRes, RESULT_ROW_END_INTERP)); - continue; - } + STimeWindow win = getActiveTimeWindow(pResultRowInfo, ts, pQuery); + bool masterScan = IS_MASTER_SCAN(pRuntimeEnv); - STimeWindow w = pRes->win; - ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &w, masterScan, &pResult, groupId); - assert(ret == TSDB_CODE_SUCCESS && !resultRowInterpolated(pResult, RESULT_ROW_END_INTERP)); + SResultRow* pResult = NULL; + int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx, + numOfOutput, pInfo->rowCellInfoOffset); + if (ret != TSDB_CODE_SUCCESS || pResult == NULL) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); + } - int32_t p = QUERY_IS_ASC_QUERY(pQuery)? 0:pDataBlockInfo->rows-1; - doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, *(TSKEY*) pRuntimeEnv->prevRow[0], -1, tsCols[0], p, w.ekey, RESULT_ROW_END_INTERP); - setResultRowInterpo(pResult, RESULT_ROW_END_INTERP); - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); + int32_t forwardStep = 0; + TSKEY ekey = reviseWindowEkey(pQuery, &win); + forwardStep = + getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true); + + // prev time window not interpolation yet. + int32_t curIndex = curTimeWindowIndex(pResultRowInfo); + if (prevIndex != -1 && prevIndex < curIndex && pQuery->timeWindowInterpo) { + for (int32_t j = prevIndex; j < curIndex; ++j) { // previous time window may be all closed already. + SResultRow* pRes = pResultRowInfo->pResult[j]; + if (pRes->closed) { + assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) && + resultRowInterpolated(pRes, RESULT_ROW_END_INTERP)); + continue; + } - doBlockwiseApplyFunctions(pRuntimeEnv, &w, startPos, 0, tsCols, pDataBlockInfo->rows, pDataBlock); + STimeWindow w = pRes->win; + ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx, + numOfOutput, pInfo->rowCellInfoOffset); + if (ret != TSDB_CODE_SUCCESS) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); } - // restore current time window - ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId); - assert (ret == TSDB_CODE_SUCCESS); - } + assert(!resultRowInterpolated(pResult, RESULT_ROW_END_INTERP)); - // window start key interpolation - doWindowBorderInterpolation(pRuntimeEnv, pDataBlockInfo, pDataBlock, pResult, &win, pQuery->pos, forwardStep); - doBlockwiseApplyFunctions(pRuntimeEnv, &win, startPos, forwardStep, tsCols, pDataBlockInfo->rows, pDataBlock); + doTimeWindowInterpolation(pOperatorInfo, pInfo, pSDataBlock->pDataBlock, *(TSKEY *)pRuntimeEnv->prevRow[0], + -1, tsCols[startPos], startPos, w.ekey, RESULT_ROW_END_INTERP); - STimeWindow nextWin = win; - while (1) { - int32_t prevEndPos = (forwardStep - 1) * step + startPos; - startPos = getNextQualifiedWindow(pRuntimeEnv, &nextWin, pDataBlockInfo, tsCols, searchFn, prevEndPos); - if (startPos < 0) { - break; - } + setResultRowInterpo(pResult, RESULT_ROW_END_INTERP); + setNotInterpoWindowKey(pInfo->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); - // null data, failed to allocate more memory buffer - int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &nextWin, masterScan, &pResult, groupId); - if (code != TSDB_CODE_SUCCESS || pResult == NULL) { - break; - } + doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &w, startPos, 0, tsCols, pSDataBlock->info.rows, + numOfOutput); + } + + // restore current time window + ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx, + numOfOutput, pInfo->rowCellInfoOffset); + if (ret != TSDB_CODE_SUCCESS) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); + } + } - ekey = reviseWindowEkey(pQuery, &nextWin); - forwardStep = getNumOfRowsInTimeWindow(pQuery, pDataBlockInfo, tsCols, startPos, ekey, searchFn, true); + // window start key interpolation + doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep); + doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, + numOfOutput); - // window start(end) key interpolation - doWindowBorderInterpolation(pRuntimeEnv, pDataBlockInfo, pDataBlock, pResult, &nextWin, startPos, forwardStep); - doBlockwiseApplyFunctions(pRuntimeEnv, &nextWin, startPos, forwardStep, tsCols, pDataBlockInfo->rows, pDataBlock); + STimeWindow nextWin = win; + while (1) { + int32_t prevEndPos = (forwardStep - 1) * step + startPos; + startPos = getNextQualifiedWindow(pQuery, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos); + if (startPos < 0) { + break; } - } else { - /* - * the sqlfunctionCtx parameters should be set done before all functions are invoked, - * since the selectivity + tag_prj query needs all parameters been set done. - * tag_prj function are changed to be TSDB_FUNC_TAG_DUMMY - */ - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - int32_t functionId = pQuery->pExpr1[k].base.functionId; - if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) { - pCtx[k].startTs = pQuery->window.skey; - aAggs[functionId].xFunction(&pCtx[k]); - } + // null data, failed to allocate more memory buffer + int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId, + pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset); + if (code != TSDB_CODE_SUCCESS || pResult == NULL) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); } + + ekey = reviseWindowEkey(pQuery, &nextWin); + forwardStep = + getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true); + + // window start(end) key interpolation + doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &nextWin, startPos, forwardStep); + doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &nextWin, startPos, forwardStep, tsCols, + pSDataBlock->info.rows, numOfOutput); } - _end: - if (pRuntimeEnv->timeWindowInterpo) { - int32_t rowIndex = QUERY_IS_ASC_QUERY(pQuery)? pDataBlockInfo->rows-1:0; - saveDataBlockLastRow(pRuntimeEnv, pDataBlockInfo, pDataBlock, rowIndex); + if (pQuery->timeWindowInterpo) { + int32_t rowIndex = ascQuery? (pSDataBlock->info.rows-1):0; + saveDataBlockLastRow(pRuntimeEnv, &pSDataBlock->info, pSDataBlock->pDataBlock, rowIndex); } + + updateResultRowInfoActiveIndex(pResultRowInfo, pQuery, pQuery->current->lastKey); } -static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, char *pData, int16_t type, int16_t bytes, int32_t groupIndex) { - SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf; +static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) { + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + STableQueryInfo* item = pRuntimeEnv->pQuery->current; - // not assign result buffer yet, add new result buffer, TODO remove it - char* d = pData; - int16_t len = bytes; - if (type == TSDB_DATA_TYPE_BINARY||type == TSDB_DATA_TYPE_NCHAR) { - d = varDataVal(pData); - len = varDataLen(pData); - } else if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) { - SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv); - qError("QInfo:%p group by not supported on double/float columns, abort", pQInfo); - return -1; + SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex); + int16_t bytes = pColInfoData->info.bytes; + int16_t type = pColInfoData->info.type; + + if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) { + qError("QInfo:%p group by not supported on double/float columns, abort", pRuntimeEnv->qinfo); + return; } - SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, d, len, true, groupIndex); - assert (pResultRow != NULL); + for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) { + char* val = ((char*)pColInfoData->pData) + bytes * j; + if (isNull(val, type)) { + continue; + } + + if (pInfo->prevData == NULL || (memcmp(pInfo->prevData, val, bytes) != 0)) { + if (pInfo->prevData == NULL) { + pInfo->prevData = malloc(bytes); + } + + memcpy(pInfo->prevData, val, bytes); + + int32_t ret = + setGroupResultOutputBuf(pRuntimeEnv, pInfo, pOperator->numOfOutput, val, type, bytes, item->groupIndex); + if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR); + } + } + + for (int32_t k = 0; k < pOperator->numOfOutput; ++k) { + pInfo->binfo.pCtx[k].size = 1; + int32_t functionId = pInfo->binfo.pCtx[k].functionId; + if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) { + aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j); + } + } + } +} +static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) { int64_t v = -1; GET_TYPED_DATA(v, int64_t, type, pData); if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { @@ -1300,94 +1361,58 @@ static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, char *pDat pResultRow->win.skey = v; pResultRow->win.ekey = v; } +} + +static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SGroupbyOperatorInfo *pInfo, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex) { + SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf; + + int32_t *rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset; + SResultRowInfo *pResultRowInfo = &pInfo->binfo.resultRowInfo; + SQLFunctionCtx *pCtx = pInfo->binfo.pCtx; + + // not assign result buffer yet, add new result buffer, TODO remove it + char* d = pData; + int16_t len = bytes; + if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + d = varDataVal(pData); + len = varDataLen(pData); + } + + SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, d, len, true, groupIndex); + assert (pResultRow != NULL); + setResultRowKey(pResultRow, pData, type); if (pResultRow->pageId == -1) { - int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->numOfRowsPerPage); + int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize); if (ret != 0) { return -1; } } - setResultOutputBuf(pRuntimeEnv, pResultRow); - initCtxOutputBuf(pRuntimeEnv); + setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset); + initCtxOutputBuffer(pCtx, numOfCols); return TSDB_CODE_SUCCESS; } -static char *getGroupbyColumnData(SQuery *pQuery, int16_t *type, int16_t *bytes, SArray* pDataBlock) { - SSqlGroupbyExpr *pGroupbyExpr = pQuery->pGroupbyExpr; - +static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) { for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) { SColIndex* pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, k); if (TSDB_COL_IS_TAG(pColIndex->flag)) { continue; } - int16_t colIndex = -1; int32_t colId = pColIndex->colId; - for (int32_t i = 0; i < pQuery->numOfCols; ++i) { - if (pQuery->colList[i].colId == colId) { - colIndex = i; - break; - } - } - - assert(colIndex >= 0 && colIndex < pQuery->numOfCols); - - *type = pQuery->colList[colIndex].type; - *bytes = pQuery->colList[colIndex].bytes; - /* - * the colIndex is acquired from the first tables of all qualified tables in this vnode during query prepare - * stage, the remain tables may not have the required column in cache actually. So, the validation of required - * column in cache with the corresponding schema is reinforced. - */ - int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); - - for (int32_t i = 0; i < numOfCols; ++i) { - SColumnInfoData *p = taosArrayGet(pDataBlock, i); - if (pColIndex->colId == p->info.colId) { - return p->pData; + for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { + SColumnInfoData* pColInfo = taosArrayGet(pDataBlock->pDataBlock, i); + if (pColInfo->info.colId == colId) { + return i; } } } - return NULL; -} - -static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, int32_t offset) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf); - SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx; - - // compare tag first - if (tVariantCompare(&pCtx[0].tag, elem.tag) != 0) { - return TS_JOIN_TAG_NOT_EQUALS; - } - - TSKEY key = *(TSKEY *)((char*)pCtx[0].pInput + TSDB_KEYSIZE * offset); - -#if defined(_DEBUG_VIEW) - printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n", - elem.ts, key, elem.tag.i64, pQuery->order.order, pRuntimeEnv->pTsBuf->tsOrder, - pRuntimeEnv->pTsBuf->cur.order, pRuntimeEnv->pTsBuf->cur.tsIndex); -#endif - - if (QUERY_IS_ASC_QUERY(pQuery)) { - if (key < elem.ts) { - return TS_JOIN_TS_NOT_EQUALS; - } else if (key > elem.ts) { - longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN); - } - } else { - if (key > elem.ts) { - return TS_JOIN_TS_NOT_EQUALS; - } else if (key < elem.ts) { - longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN); - } - } - - return TS_JOIN_TS_EQUAL; + assert(0); + return -1; } static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) { @@ -1412,613 +1437,306 @@ static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx return pCtx->param[0].i64 == pQuery->order.order; } - // in the supplementary scan, only the following functions need to be executed - if (IS_REVERSE_SCAN(pRuntimeEnv)) { + // in the reverse table scan, only the following functions need to be executed + if (IS_REVERSE_SCAN(pRuntimeEnv) || + (pRuntimeEnv->scanFlag == REPEAT_SCAN && functionId != TSDB_FUNC_STDDEV && functionId != TSDB_FUNC_PERCT)) { return false; } return true; } -void doRowwiseTimeWindowInterpolation(SQueryRuntimeEnv *pRuntimeEnv, SArray *pDataBlock, TSKEY prevTs, - int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, - int32_t type) { - SQuery *pQuery = pRuntimeEnv->pQuery; - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - int32_t functionId = pQuery->pExpr1[k].base.functionId; - if (functionId != TSDB_FUNC_TWA && functionId != TSDB_FUNC_INTERP) { - pRuntimeEnv->pCtx[k].start.key = INT64_MIN; - continue; - } - - SColIndex * pColIndex = &pQuery->pExpr1[k].base.colInfo; - int16_t index = pColIndex->colIndex; - SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, index); +void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex) { + SDataStatis *pStatis = NULL; - assert(pColInfo->info.colId == pColIndex->colId && curTs != windowKey); - double v1 = 0, v2 = 0, v = 0; + if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) { + pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex]; - if (prevRowIndex == -1) { - GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pRuntimeEnv->prevRow[index]); - } else { - GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pColInfo->pData + prevRowIndex * pColInfo->info.bytes); - } + pCtx->preAggVals.statis = *pStatis; + pCtx->preAggVals.isSet = true; + assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows); + } else { + pCtx->preAggVals.isSet = false; + } - GET_TYPED_DATA(v2, double, pColInfo->info.type, (char *)pColInfo->pData + curRowIndex * pColInfo->info.bytes); + pCtx->hasNull = hasNullRv(pColIndex, pStatis); - SPoint point1 = (SPoint){.key = prevTs, .val = &v1}; - SPoint point2 = (SPoint){.key = curTs, .val = &v2}; - SPoint point = (SPoint){.key = windowKey, .val = &v}; + // set the statistics data for primary time stamp column + if (pCtx->functionId == TSDB_FUNC_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { + pCtx->preAggVals.isSet = true; + pCtx->preAggVals.statis.min = pSDataBlock->info.window.skey; + pCtx->preAggVals.statis.max = pSDataBlock->info.window.ekey; + } +} - if (functionId == TSDB_FUNC_TWA) { - taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE); +// set the output buffer for the selectivity + tag query +static int32_t setCtxTagColumnInfo(SQLFunctionCtx *pCtx, int32_t numOfOutput) { + if (!isSelectivityWithTagsQuery(pCtx, numOfOutput)) { + return TSDB_CODE_SUCCESS; + } - if (type == RESULT_ROW_START_INTERP) { - pRuntimeEnv->pCtx[k].start.key = point.key; - pRuntimeEnv->pCtx[k].start.val = v; - } else { - pRuntimeEnv->pCtx[k].end.key = point.key; - pRuntimeEnv->pCtx[k].end.val = v; - } - } else { - if (type == RESULT_ROW_START_INTERP) { - pRuntimeEnv->pCtx[k].start.key = prevTs; - pRuntimeEnv->pCtx[k].start.val = v1; + int32_t num = 0; + int16_t tagLen = 0; - pRuntimeEnv->pCtx[k].end.key = curTs; - pRuntimeEnv->pCtx[k].end.val = v2; - } - } + SQLFunctionCtx* p = NULL; + SQLFunctionCtx** pTagCtx = calloc(numOfOutput, POINTER_BYTES); + if (pTagCtx == NULL) { + return TSDB_CODE_QRY_OUT_OF_MEMORY; } -} - -static void setTimeWindowSKeyInterp(SQueryRuntimeEnv* pRuntimeEnv, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY ts, int32_t offset, SResultRow* pResult, STimeWindow* win) { - SQuery* pQuery = pRuntimeEnv->pQuery; - bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP); - if (!done) { - TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->skey:win->ekey; - if (key == ts) { - setResultRowInterpo(pResult, RESULT_ROW_START_INTERP); - } else if (prevTs != INT64_MIN && ((QUERY_IS_ASC_QUERY(pQuery) && prevTs < key) || (!QUERY_IS_ASC_QUERY(pQuery) && prevTs > key))) { - doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, key, RESULT_ROW_START_INTERP); - setResultRowInterpo(pResult, RESULT_ROW_START_INTERP); + for (int32_t i = 0; i < numOfOutput; ++i) { + int32_t functionId = pCtx[i].functionId; + + if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { + tagLen += pCtx[i].outputBytes; + pTagCtx[num++] = &pCtx[i]; + } else if ((aAggs[functionId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) { + p = &pCtx[i]; + } else if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG) { + // tag function may be the group by tag column + // ts may be the required primary timestamp column + continue; } else { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); - } - - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP); - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - pRuntimeEnv->pCtx[k].size = 1; + // the column may be the normal column, group by normal_column, the functionId is TSDB_FUNC_PRJ } + } + if (p != NULL) { + p->tagInfo.pTagCtxList = pTagCtx; + p->tagInfo.numOfTagCols = num; + p->tagInfo.tagsLen = tagLen; } else { - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); + tfree(pTagCtx); } + + return TSDB_CODE_SUCCESS; } -static void setTimeWindowEKeyInterp(SQueryRuntimeEnv* pRuntimeEnv, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY ts, int32_t offset, SResultRow* pResult, STimeWindow* win) { +static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput, + int32_t** rowCellInfoOffset) { SQuery* pQuery = pRuntimeEnv->pQuery; - TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->ekey:win->skey; - doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, key, RESULT_ROW_END_INTERP); - setResultRowInterpo(pResult, RESULT_ROW_END_INTERP); - - setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP); - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - pRuntimeEnv->pCtx[i].size = 0; + SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx)); + if (pFuncCtx == NULL) { + return NULL; } -} - -static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pStatis, SDataBlockInfo *pDataBlockInfo, - SResultRowInfo *pWindowResInfo, SArray *pDataBlock) { - SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx; - bool masterScan = IS_MASTER_SCAN(pRuntimeEnv); - - SQuery *pQuery = pRuntimeEnv->pQuery; - STableQueryInfo* item = pQuery->current; - - int64_t groupId = item->groupIndex; - SColumnInfoData* pColumnInfoData = (SColumnInfoData *)taosArrayGet(pDataBlock, 0); - - TSKEY *tsCols = (pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP)? (TSKEY*) pColumnInfoData->pData:NULL; - bool groupbyColumnValue = pRuntimeEnv->groupbyColumn; - - int16_t type = 0; - int16_t bytes = 0; - - char *groupbyColumnData = NULL; - if (groupbyColumnValue) { - groupbyColumnData = getGroupbyColumnData(pQuery, &type, &bytes, pDataBlock); + *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t)); + if (*rowCellInfoOffset == 0) { + tfree(pFuncCtx); + return NULL; } - SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv); - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - char *dataBlock = getDataBlock(pRuntimeEnv, &pRuntimeEnv->sasArray[k], k, pDataBlockInfo->rows, pDataBlock); - setExecParams(pQuery, &pCtx[k], dataBlock, tsCols, pDataBlockInfo, pStatis, &pQuery->pExpr1[k]); - pCtx[k].size = 1; - } + for (int32_t i = 0; i < numOfOutput; ++i) { + SSqlFuncMsg *pSqlFuncMsg = &pExpr[i].base; + SQLFunctionCtx* pCtx = &pFuncCtx[i]; - // set the input column data - for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) { - SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k]; - pFilterInfo->pData = getDataBlockImpl(pDataBlock, pFilterInfo->info.colId); - assert(pFilterInfo->pData != NULL); - } + SColIndex *pIndex = &pSqlFuncMsg->colInfo; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); + if (TSDB_COL_REQ_NULL(pIndex->flag)) { + pCtx->requireNull = true; + pIndex->flag &= ~(TSDB_COL_NULL); + } else { + pCtx->requireNull = false; + } - // from top to bottom in desc - // from bottom to top in asc order - if (pRuntimeEnv->pTsBuf != NULL) { - qDebug("QInfo:%p process data rows, numOfRows:%d, query order:%d, ts comp order:%d", pQInfo, pDataBlockInfo->rows, - pQuery->order.order, pRuntimeEnv->pTsBuf->cur.order); - } + pCtx->inputBytes = pSqlFuncMsg->colBytes; + pCtx->inputType = pSqlFuncMsg->colType; - int32_t offset = -1; - TSKEY prevTs = *(TSKEY*) pRuntimeEnv->prevRow[0]; - int32_t prevRowIndex = -1; + pCtx->ptsOutputBuf = NULL; - for (int32_t j = 0; j < pDataBlockInfo->rows; ++j) { - offset = GET_COL_DATA_POS(pQuery, j, step); + pCtx->outputBytes = pExpr[i].bytes; + pCtx->outputType = pExpr[i].type; - if (pRuntimeEnv->pTsBuf != NULL) { - int32_t ret = doTSJoinFilter(pRuntimeEnv, offset); - if (ret == TS_JOIN_TAG_NOT_EQUALS) { - break; - } else if (ret == TS_JOIN_TS_NOT_EQUALS) { + pCtx->order = pQuery->order.order; + pCtx->functionId = pSqlFuncMsg->functionId; + pCtx->stableQuery = pQuery->stableQuery; + pCtx->interBufBytes = pExpr[i].interBytes; + pCtx->start.key = INT64_MIN; + pCtx->end.key = INT64_MIN; + + pCtx->numOfParams = pSqlFuncMsg->numOfParams; + for (int32_t j = 0; j < pCtx->numOfParams; ++j) { + int16_t type = pSqlFuncMsg->arg[j].argType; + int16_t bytes = pSqlFuncMsg->arg[j].argBytes; + if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) { continue; - } else { - assert(ret == TS_JOIN_TS_EQUAL); } - } - if (pQuery->numOfFilterCols > 0 && (!doFilterData(pQuery, offset))) { - continue; + if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type); + } else { + tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type); + } } - // interval window query, decide the time window according to the primary timestamp - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - int32_t prevWindowIndex = curTimeWindowIndex(pWindowResInfo); - int64_t ts = tsCols[offset]; - - STimeWindow win = getActiveTimeWindow(pWindowResInfo, ts, pQuery); + // set the order information for top/bottom query + int32_t functionId = pCtx->functionId; - SResultRow* pResult = NULL; - int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId); - if (ret != TSDB_CODE_SUCCESS || pResult == NULL) { // null data, too many state code - goto _end; - } + if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { + int32_t f = pExpr[0].base.functionId; + assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY); - // window start key interpolation - if (pRuntimeEnv->timeWindowInterpo) { - // check for the time window end time interpolation - int32_t curIndex = curTimeWindowIndex(pWindowResInfo); - if (prevWindowIndex != -1 && prevWindowIndex < curIndex) { - for (int32_t k = prevWindowIndex; k < curIndex; ++k) { - SResultRow *pRes = pWindowResInfo->pResult[k]; - if (pRes->closed) { - assert(resultRowInterpolated(pResult, RESULT_ROW_START_INTERP) && resultRowInterpolated(pResult, RESULT_ROW_END_INTERP)); - continue; - } + pCtx->param[2].i64 = pQuery->order.order; + pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT; + pCtx->param[3].i64 = functionId; + pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT; - ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &pRes->win, masterScan, &pResult, groupId); - assert(ret == TSDB_CODE_SUCCESS && !resultRowInterpolated(pResult, RESULT_ROW_END_INTERP)); - - setTimeWindowEKeyInterp(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, pResult, &pRes->win); - doRowwiseApplyFunctions(pRuntimeEnv, &pRes->win, offset); - } - - // restore current time window - ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId); - if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code - continue; - } - } - - setTimeWindowSKeyInterp(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, pResult, &win); - } - - doRowwiseApplyFunctions(pRuntimeEnv, &win, offset); - int32_t index = pWindowResInfo->curIndex; - - STimeWindow nextWin = win; - while (1) { - getNextTimeWindow(pQuery, &nextWin); - if ((nextWin.skey > pQuery->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || - (nextWin.ekey < pQuery->window.ekey && !QUERY_IS_ASC_QUERY(pQuery))) { - break; - } - - if (ts < nextWin.skey || ts > nextWin.ekey) { - break; - } - - // null data, failed to allocate more memory buffer - int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &nextWin, masterScan, &pResult, groupId); - if (code != TSDB_CODE_SUCCESS || pResult == NULL) { - break; - } - - setTimeWindowSKeyInterp(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, pResult, &nextWin); - doRowwiseApplyFunctions(pRuntimeEnv, &nextWin, offset); - } - - // restore the index, add the result row will move the index - pWindowResInfo->curIndex = index; - } else { // other queries - // decide which group this rows belongs to according to current state value - char* val = NULL; - if (groupbyColumnValue) { - val = groupbyColumnData + bytes * offset; - if (isNull(val, type)) { // ignore the null value - continue; - } - - int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, val, type, bytes, item->groupIndex); - if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code - longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR); - } - } - - if (pRuntimeEnv->stabledev) { - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - int32_t functionId = pQuery->pExpr1[k].base.functionId; - if (functionId != TSDB_FUNC_STDDEV_DST) { - continue; - } - - pRuntimeEnv->pCtx[k].param[0].arr = NULL; - pRuntimeEnv->pCtx[k].param[0].nType = TSDB_DATA_TYPE_INT; // avoid freeing the memory by setting the type to be int - - // todo opt perf - int32_t numOfGroup = (int32_t)taosArrayGetSize(pRuntimeEnv->prevResult); - for (int32_t i = 0; i < numOfGroup; ++i) { - SInterResult *p = taosArrayGet(pRuntimeEnv->prevResult, i); - if (memcmp(p->tags, val, bytes) == 0) { - int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult); - for (int32_t f = 0; f < numOfCols; ++f) { - SStddevInterResult *pres = taosArrayGet(p->pResult, f); - if (pres->colId == pQuery->pExpr1[k].base.colInfo.colId) { - pRuntimeEnv->pCtx[k].param[0].arr = pres->pResult; - break; - } - } - } + pCtx->param[1].i64 = pQuery->order.orderColId; + } else if (functionId == TSDB_FUNC_INTERP) { + pCtx->param[2].i64 = (int8_t)pQuery->fillType; + if (pQuery->fillVal != NULL) { + if (isNull((const char *)&pQuery->fillVal[i], pCtx->inputType)) { + pCtx->param[1].nType = TSDB_DATA_TYPE_NULL; + } else { // todo refactor, tVariantCreateFromBinary should handle the NULL value + if (pCtx->inputType != TSDB_DATA_TYPE_BINARY && pCtx->inputType != TSDB_DATA_TYPE_NCHAR) { + tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQuery->fillVal[i], pCtx->inputBytes, pCtx->inputType); } } } - - for (int32_t k = 0; k < pQuery->numOfOutput; ++k) { - int32_t functionId = pQuery->pExpr1[k].base.functionId; - if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) { - aAggs[functionId].xFunctionF(&pCtx[k], offset); - } - } - } - - prevTs = tsCols[offset]; - prevRowIndex = offset; - - if (pRuntimeEnv->pTsBuf != NULL) { - // if timestamp filter list is empty, quit current query - if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) { - setQueryStatus(pQuery, QUERY_COMPLETED); - break; - } + } else if (functionId == TSDB_FUNC_TS_COMP) { + pCtx->param[0].i64 = pQuery->vgId; //TODO this should be the parameter from client + pCtx->param[0].nType = TSDB_DATA_TYPE_BIGINT; + } else if (functionId == TSDB_FUNC_TWA) { + pCtx->param[1].i64 = pQuery->window.skey; + pCtx->param[1].nType = TSDB_DATA_TYPE_BIGINT; + pCtx->param[2].i64 = pQuery->window.ekey; + pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT; + } else if (functionId == TSDB_FUNC_ARITHM) { + pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i]; } } - _end: - assert(offset >= 0 && tsCols != NULL); - if (prevTs != INT64_MIN && prevTs != *(int64_t*)pRuntimeEnv->prevRow[0]) { - assert(prevRowIndex >= 0); - item->lastKey = prevTs + step; - } - - // In case of all rows in current block are not qualified - if (pRuntimeEnv->timeWindowInterpo && prevRowIndex != -1) { - saveDataBlockLastRow(pRuntimeEnv, pDataBlockInfo, pDataBlock, prevRowIndex); - } - - if (pRuntimeEnv->pTsBuf != NULL) { - item->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); - } -} - -static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pDataBlockInfo, - SDataStatis *pStatis, __block_search_fn_t searchFn, SArray *pDataBlock) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - STableQueryInfo* pTableQueryInfo = pQuery->current; - SResultRowInfo* pResultRowInfo = &pRuntimeEnv->resultRowInfo; - - if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->groupbyColumn) { - rowwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, pDataBlock); - } else { - blockwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, searchFn, pDataBlock); + for(int32_t i = 1; i < numOfOutput; ++i) { + (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) + + pExpr[i - 1].interBytes * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery)); } - // update the lastkey of current table for projection/aggregation query - TSKEY lastKey = QUERY_IS_ASC_QUERY(pQuery) ? pDataBlockInfo->window.ekey : pDataBlockInfo->window.skey; - pTableQueryInfo->lastKey = lastKey + GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - - // interval query with limit applied - int32_t numOfRes = 0; - if (QUERY_IS_INTERVAL_QUERY(pQuery) || pRuntimeEnv->groupbyColumn) { - numOfRes = pResultRowInfo->size; - updateResultRowIndex(pResultRowInfo, pTableQueryInfo, QUERY_IS_ASC_QUERY(pQuery), pRuntimeEnv->timeWindowInterpo); - } else { // projection query - numOfRes = (int32_t) getNumOfResult(pRuntimeEnv); - - // update the number of output result - if (numOfRes > 0 && pQuery->checkResultBuf == 1) { - assert(numOfRes >= pQuery->rec.rows); - pQuery->rec.rows = numOfRes; - - if (numOfRes >= pQuery->rec.threshold) { - setQueryStatus(pQuery, QUERY_RESBUF_FULL); - } - - if ((pQuery->limit.limit >= 0) && (pQuery->limit.limit + pQuery->limit.offset) <= numOfRes) { - setQueryStatus(pQuery, QUERY_COMPLETED); - } - - if (((pTableQueryInfo->lastKey > pTableQueryInfo->win.ekey) && QUERY_IS_ASC_QUERY(pQuery)) || - ((pTableQueryInfo->lastKey < pTableQueryInfo->win.ekey) && (!QUERY_IS_ASC_QUERY(pQuery)))) { - setQueryStatus(pQuery, QUERY_COMPLETED); - } - } - } + setCtxTagColumnInfo(pFuncCtx, numOfOutput); - return numOfRes; + return pFuncCtx; } -void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void* inputData, TSKEY *tsCol, SDataBlockInfo* pBlockInfo, - SDataStatis *pStatis, SExprInfo* pExprInfo) { - - int32_t functionId = pExprInfo->base.functionId; - int32_t colId = pExprInfo->base.colInfo.colId; - - SDataStatis *tpField = NULL; - pCtx->hasNull = hasNullValue(&pExprInfo->base.colInfo, pStatis, &tpField); - - if (tpField != NULL) { - pCtx->preAggVals.isSet = true; - pCtx->preAggVals.statis = *tpField; - assert(pCtx->preAggVals.statis.numOfNull <= pBlockInfo->rows); - } else { - pCtx->preAggVals.isSet = false; - } - - pCtx->preAggVals.dataBlockLoaded = (inputData != NULL); - - // limit/offset query will affect this value - pCtx->size = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->rows - pQuery->pos : pQuery->pos + 1; - - // set the start position in current block - int32_t offset = QUERY_IS_ASC_QUERY(pQuery) ? pQuery->pos: (pQuery->pos - pCtx->size + 1); - if (inputData != NULL) { - pCtx->pInput = (char*)inputData + offset * pCtx->inputBytes; - } - - uint32_t status = aAggs[functionId].status; - if (((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) && (tsCol != NULL)) { - pCtx->ptsList = tsCol + offset; - } - - if (functionId == TSDB_FUNC_SPREAD) { // set the statistics data for primary time stamp column - if (colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { - pCtx->preAggVals.isSet = true; - pCtx->preAggVals.statis.min = pBlockInfo->window.skey; - pCtx->preAggVals.statis.max = pBlockInfo->window.ekey; - } +static void* destroySQLFunctionCtx(SQLFunctionCtx* pCtx, int32_t numOfOutput) { + if (pCtx == NULL) { + return NULL; } -} - -// set the output buffer for the selectivity + tag query -static int32_t setCtxTagColumnInfo(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx) { - SQuery* pQuery = pRuntimeEnv->pQuery; - if (isSelectivityWithTagsQuery(pQuery)) { - int32_t num = 0; - int16_t tagLen = 0; - - SQLFunctionCtx *p = NULL; - SQLFunctionCtx **pTagCtx = calloc(pQuery->numOfOutput, POINTER_BYTES); - if (pTagCtx == NULL) { - return TSDB_CODE_QRY_OUT_OF_MEMORY; + for (int32_t i = 0; i < numOfOutput; ++i) { + for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) { + tVariantDestroy(&pCtx[i].param[j]); } - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SSqlFuncMsg *pSqlFuncMsg = &pQuery->pExpr1[i].base; - - if (pSqlFuncMsg->functionId == TSDB_FUNC_TAG_DUMMY || pSqlFuncMsg->functionId == TSDB_FUNC_TS_DUMMY) { - tagLen += pCtx[i].outputBytes; - pTagCtx[num++] = &pCtx[i]; - } else if ((aAggs[pSqlFuncMsg->functionId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) { - p = &pCtx[i]; - } else if (pSqlFuncMsg->functionId == TSDB_FUNC_TS || pSqlFuncMsg->functionId == TSDB_FUNC_TAG) { - // tag function may be the group by tag column - // ts may be the required primary timestamp column - continue; - } else { - // the column may be the normal column, group by normal_column, the functionId is TSDB_FUNC_PRJ - } - } - if (p != NULL) { - p->tagInfo.pTagCtxList = pTagCtx; - p->tagInfo.numOfTagCols = num; - p->tagInfo.tagsLen = tagLen; - } else { - tfree(pTagCtx); - } + tVariantDestroy(&pCtx[i].tag); + tfree(pCtx[i].tagInfo.pTagCtxList); } - return TSDB_CODE_SUCCESS; + tfree(pCtx); + return NULL; } -static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables, int16_t order, int32_t vgId) { - qDebug("QInfo:%p setup runtime env", GET_QINFO_ADDR(pRuntimeEnv)); +static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables) { + qDebug("QInfo:%p setup runtime env", pRuntimeEnv->qinfo); SQuery *pQuery = pRuntimeEnv->pQuery; - pRuntimeEnv->interBufSize = getOutputInterResultBufSize(pQuery); - pRuntimeEnv->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo)); + pRuntimeEnv->prevGroupId = INT32_MIN; + pRuntimeEnv->pQuery = pQuery; pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); pRuntimeEnv->keyBuf = malloc(pQuery->maxSrcColumnSize + sizeof(int64_t)); pRuntimeEnv->pool = initResultRowPool(getResultRowSize(pRuntimeEnv)); pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQuery->numOfCols + pQuery->srcRowSize); pRuntimeEnv->tagVal = malloc(pQuery->tagLen); - pRuntimeEnv->pCtx = (SQLFunctionCtx *)calloc(pQuery->numOfOutput, sizeof(SQLFunctionCtx)); - pRuntimeEnv->offset = calloc(pQuery->numOfOutput, sizeof(int16_t)); - pRuntimeEnv->rowCellInfoOffset = calloc(pQuery->numOfOutput, sizeof(int32_t)); + pRuntimeEnv->currentOffset = pQuery->limit.offset; + + // NOTE: pTableCheckInfo need to update the query time range and the lastKey info + pRuntimeEnv->pTableRetrieveTsMap = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); + pRuntimeEnv->sasArray = calloc(pQuery->numOfOutput, sizeof(SArithmeticSupport)); - if (pRuntimeEnv->offset == NULL || pRuntimeEnv->pCtx == NULL || pRuntimeEnv->rowCellInfoOffset == NULL || - pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL || - pRuntimeEnv->prevRow == NULL || pRuntimeEnv->tagVal == NULL) { + if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL || + pRuntimeEnv->prevRow == NULL || pRuntimeEnv->tagVal == NULL) { goto _clean; } - char* start = POINTER_BYTES * pQuery->numOfCols + (char*) pRuntimeEnv->prevRow; - pRuntimeEnv->prevRow[0] = start; - for(int32_t i = 1; i < pQuery->numOfCols; ++i) { - pRuntimeEnv->prevRow[i] = pRuntimeEnv->prevRow[i - 1] + pQuery->colList[i-1].bytes; - } - - pRuntimeEnv->offset[0] = 0; - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SSqlFuncMsg *pSqlFuncMsg = &pQuery->pExpr1[i].base; - - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; - SColIndex * pIndex = &pSqlFuncMsg->colInfo; - - if (TSDB_COL_REQ_NULL(pIndex->flag)) { - pCtx->requireNull = true; - pIndex->flag &= ~(TSDB_COL_NULL); - } else { - pCtx->requireNull = false; - } - - int32_t index = pSqlFuncMsg->colInfo.colIndex; - if (TSDB_COL_IS_TAG(pIndex->flag)) { - if (pIndex->colId == TSDB_TBNAME_COLUMN_INDEX) { // todo refactor - SSchema *s = tGetTbnameColumnSchema(); - - pCtx->inputBytes = s->bytes; - pCtx->inputType = s->type; - } else if (pIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) { - SSchema s = tGetBlockDistColumnSchema(); - pCtx->inputBytes = s.bytes; - pCtx->inputType = s.type; - } else { - pCtx->inputBytes = pQuery->tagColList[index].bytes; - pCtx->inputType = pQuery->tagColList[index].type; - } - } else if (TSDB_COL_IS_UD_COL(pIndex->flag)) { - pCtx->inputBytes = pSqlFuncMsg->arg[0].argBytes; - pCtx->inputType = pSqlFuncMsg->arg[0].argType; - } else { - pCtx->inputBytes = pQuery->colList[index].bytes; - pCtx->inputType = pQuery->colList[index].type; + if (pQuery->numOfCols) { + char* start = POINTER_BYTES * pQuery->numOfCols + (char*) pRuntimeEnv->prevRow; + pRuntimeEnv->prevRow[0] = start; + for(int32_t i = 1; i < pQuery->numOfCols; ++i) { + pRuntimeEnv->prevRow[i] = pRuntimeEnv->prevRow[i - 1] + pQuery->colList[i-1].bytes; } - assert(isValidDataType(pCtx->inputType)); - pCtx->ptsOutputBuf = NULL; + *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN; + } - pCtx->outputBytes = pQuery->pExpr1[i].bytes; - pCtx->outputType = pQuery->pExpr1[i].type; + qDebug("QInfo:%p init runtime environment completed", pRuntimeEnv->qinfo); - pCtx->order = pQuery->order.order; - pCtx->functionId = pSqlFuncMsg->functionId; - pCtx->stableQuery = pRuntimeEnv->stableQuery; - pCtx->interBufBytes = pQuery->pExpr1[i].interBytes; - pCtx->start.key = INT64_MIN; - pCtx->end.key = INT64_MIN; + // group by normal column, sliding window query, interval query are handled by interval query processor + // interval (down sampling operation) + if (onlyQueryTags(pQuery)) { // do nothing for tags query + + } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) { + if (pQuery->stableQuery) { + pRuntimeEnv->proot = createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, + pQuery->pExpr1, pQuery->numOfOutput); + setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot); + } else { + pRuntimeEnv->proot = + createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput); + setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot); - pCtx->numOfParams = pSqlFuncMsg->numOfParams; - for (int32_t j = 0; j < pCtx->numOfParams; ++j) { - int16_t type = pSqlFuncMsg->arg[j].argType; - int16_t bytes = pSqlFuncMsg->arg[j].argBytes; - if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) { - continue; + if (pQuery->pExpr2 != NULL) { + pRuntimeEnv->proot = + createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2); } - if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type); - } else { - tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type); + if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) { + SOperatorInfo* pInfo = pRuntimeEnv->proot; + pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput); } } - // set the order information for top/bottom query - int32_t functionId = pCtx->functionId; - - if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { - int32_t f = pQuery->pExpr1[0].base.functionId; - assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY); + } else if (pQuery->groupbyColumn) { + pRuntimeEnv->proot = + createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput); + setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot); - pCtx->param[2].i64 = order; - pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT; - pCtx->param[3].i64 = functionId; - pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT; + if (pQuery->pExpr2 != NULL) { + pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2); + } + } else if (isFixedOutputQuery(pQuery)) { + if (pQuery->stableQuery && !isTsCompQuery(pQuery)) { + pRuntimeEnv->proot = + createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput); + } else { + pRuntimeEnv->proot = + createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput); + } - pCtx->param[1].i64 = pQuery->order.orderColId; - } else if (functionId == TSDB_FUNC_INTERP) { - pCtx->param[2].i64 = (int8_t)pQuery->fillType; - if (pQuery->fillVal != NULL) { - if (isNull((const char *)&pQuery->fillVal[i], pCtx->inputType)) { - pCtx->param[1].nType = TSDB_DATA_TYPE_NULL; - } else { // todo refactor, tVariantCreateFromBinary should handle the NULL value - if (pCtx->inputType != TSDB_DATA_TYPE_BINARY && pCtx->inputType != TSDB_DATA_TYPE_NCHAR) { - tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQuery->fillVal[i], pCtx->inputBytes, pCtx->inputType); - } - } - } - } else if (functionId == TSDB_FUNC_TS_COMP) { - pCtx->param[0].i64 = vgId; - pCtx->param[0].nType = TSDB_DATA_TYPE_BIGINT; - } else if (functionId == TSDB_FUNC_TWA) { - pCtx->param[1].i64 = pQuery->window.skey; - pCtx->param[1].nType = TSDB_DATA_TYPE_BIGINT; - pCtx->param[2].i64 = pQuery->window.ekey; - pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT; - } else if (functionId == TSDB_FUNC_ARITHM) { - pRuntimeEnv->sasArray[i].data = calloc(pQuery->numOfCols, POINTER_BYTES); - if (pRuntimeEnv->sasArray[i].data == NULL) { - goto _clean; - } + setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot); - pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i]; + if (pQuery->pExpr2 != NULL) { + pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2); } - - if (i > 0) { - pRuntimeEnv->offset[i] = pRuntimeEnv->offset[i - 1] + pRuntimeEnv->pCtx[i - 1].outputBytes; - pRuntimeEnv->rowCellInfoOffset[i] = - pRuntimeEnv->rowCellInfoOffset[i - 1] + sizeof(SResultRowCellInfo) + pQuery->pExpr1[i - 1].interBytes; + } else { // diff/add/multiply/subtract/division + assert(pQuery->checkResultBuf == 1); + if (!onlyQueryTags(pQuery)) { + pRuntimeEnv->proot = + createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput); + setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot); } } - *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN; - - // if it is group by normal column, do not set output buffer, the output buffer is pResult - // fixed output query/multi-output query for normal table - if (!pRuntimeEnv->groupbyColumn && !pRuntimeEnv->stableQuery && !QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQuery)) { - resetDefaultResInfoOutputBuf(pRuntimeEnv); + if (pQuery->limit.offset > 0) { + pRuntimeEnv->proot = createOffsetOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot); } - if (setCtxTagColumnInfo(pRuntimeEnv, pRuntimeEnv->pCtx) != TSDB_CODE_SUCCESS) { - goto _clean; + if (pQuery->limit.limit > 0) { + pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot); } - qDebug("QInfo:%p init runtime completed", GET_QINFO_ADDR(pRuntimeEnv)); return TSDB_CODE_SUCCESS; _clean: - tfree(pRuntimeEnv->pCtx); - tfree(pRuntimeEnv->offset); - tfree(pRuntimeEnv->rowCellInfoOffset); tfree(pRuntimeEnv->sasArray); tfree(pRuntimeEnv->pResultRowHashTable); tfree(pRuntimeEnv->keyBuf); @@ -2028,74 +1746,37 @@ _clean: return TSDB_CODE_QRY_OUT_OF_MEMORY; } -static void doFreeQueryHandle(SQInfo* pQInfo) { - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; +static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) { + SQuery* pQuery = pRuntimeEnv->pQuery; tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle); - tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); - pRuntimeEnv->pQueryHandle = NULL; - pRuntimeEnv->pSecQueryHandle = NULL; - SMemRef* pMemRef = &pQInfo->memRef; + SMemRef* pMemRef = &pQuery->memRef; assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL); } - static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { - if (pRuntimeEnv->pQuery == NULL) { - return; - } - SQuery *pQuery = pRuntimeEnv->pQuery; - SQInfo* pQInfo = (SQInfo*) GET_QINFO_ADDR(pRuntimeEnv); + SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo; qDebug("QInfo:%p teardown runtime env", pQInfo); - cleanupResultRowInfo(&pRuntimeEnv->resultRowInfo); - - if (isTsCompQuery(pQuery)) { - FILE *f = *(FILE **)pQuery->sdata[0]->data; - - if (f) { - fclose(f); - *(FILE **)pQuery->sdata[0]->data = NULL; - } - } - - - if (pRuntimeEnv->pCtx != NULL) { - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; - - for (int32_t j = 0; j < pCtx->numOfParams; ++j) { - tVariantDestroy(&pCtx->param[j]); - } - - tVariantDestroy(&pCtx->tag); - tfree(pCtx->tagInfo.pTagCtxList); - } - - tfree(pRuntimeEnv->pCtx); - } if (pRuntimeEnv->sasArray != NULL) { for(int32_t i = 0; i < pQuery->numOfOutput; ++i) { tfree(pRuntimeEnv->sasArray[i].data); + tfree(pRuntimeEnv->sasArray[i].colList); } tfree(pRuntimeEnv->sasArray); } - pRuntimeEnv->pFillInfo = taosDestroyFillInfo(pRuntimeEnv->pFillInfo); - destroyResultBuf(pRuntimeEnv->pResultBuf); - doFreeQueryHandle(pQInfo); + doFreeQueryHandle(pRuntimeEnv); pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf); - tfree(pRuntimeEnv->offset); tfree(pRuntimeEnv->keyBuf); - tfree(pRuntimeEnv->rowCellInfoOffset); tfree(pRuntimeEnv->prevRow); tfree(pRuntimeEnv->tagVal); @@ -2105,6 +1786,11 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { pRuntimeEnv->pool = destroyResultRowPool(pRuntimeEnv->pool); taosArrayDestroyEx(pRuntimeEnv->prevResult, freeInterResult); pRuntimeEnv->prevResult = NULL; + + taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap); + pRuntimeEnv->pTableRetrieveTsMap = NULL; + + destroyOperatorInfo(pRuntimeEnv->proot); } static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) { @@ -2132,14 +1818,13 @@ bool isQueryKilled(SQInfo *pQInfo) { void setQueryKilled(SQInfo *pQInfo) { pQInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED;} -static bool isFixedOutputQuery(SQueryRuntimeEnv* pRuntimeEnv) { - SQuery* pQuery = pRuntimeEnv->pQuery; +static bool isFixedOutputQuery(SQuery* pQuery) { if (QUERY_IS_INTERVAL_QUERY(pQuery)) { return false; } // Note:top/bottom query is fixed output query - if (pRuntimeEnv->topBotQuery || pRuntimeEnv->groupbyColumn) { + if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) { return true; } @@ -2177,7 +1862,7 @@ bool isPointInterpoQuery(SQuery *pQuery) { } // TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION -static bool isSumAvgRateQuery(SQuery *pQuery) { +static UNUSED_FUNC bool isSumAvgRateQuery(SQuery *pQuery) { for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t functionId = pQuery->pExpr1[i].base.functionId; if (functionId == TSDB_FUNC_TS) { @@ -2294,11 +1979,11 @@ static void setScanLimitationByResultBuffer(SQuery *pQuery) { /* * todo add more parameters to check soon.. */ -bool colIdCheck(SQuery *pQuery) { +bool colIdCheck(SQuery *pQuery, void* qinfo) { // load data column information is incorrect for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) { if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) { - qError("QInfo:%p invalid data load column for query", GET_QINFO_ADDR(pQuery)); + qError("QInfo:%p invalid data load column for query", qinfo); return false; } } @@ -2330,9 +2015,10 @@ static bool onlyFirstQuery(SQuery *pQuery) { return onlyOneQueryType(pQuery, TSD static bool onlyLastQuery(SQuery *pQuery) { return onlyOneQueryType(pQuery, TSDB_FUNC_LAST, TSDB_FUNC_LAST_DST); } static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) { - size_t t = taosArrayGetSize(pQInfo->tableGroupInfo.pGroupList); + SQuery* pQuery = &pQInfo->query; + size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList); for(int32_t i = 0; i < t; ++i) { - SArray* p1 = taosArrayGetP(pQInfo->tableGroupInfo.pGroupList, i); + SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i); size_t len = taosArrayGetSize(p1); for(int32_t j = 0; j < len; ++j) { @@ -2378,8 +2064,7 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) { if (!QUERY_IS_ASC_QUERY(pQuery)) { - qDebug(msg, GET_QINFO_ADDR(pQuery), "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, - pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); + qDebug(msg, pQInfo, "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); } @@ -2390,7 +2075,7 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo if (pQuery->interval.interval == 0) { if (onlyFirstQuery(pQuery)) { if (!QUERY_IS_ASC_QUERY(pQuery)) { - qDebug(msg, GET_QINFO_ADDR(pQuery), "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, + qDebug(msg, pQInfo, "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); @@ -2400,7 +2085,7 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo pQuery->order.order = TSDB_ORDER_ASC; } else if (onlyLastQuery(pQuery)) { if (QUERY_IS_ASC_QUERY(pQuery)) { - qDebug(msg, GET_QINFO_ADDR(pQuery), "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey, + qDebug(msg, pQInfo, "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); @@ -2414,7 +2099,7 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo if (stableQuery) { if (onlyFirstQuery(pQuery)) { if (!QUERY_IS_ASC_QUERY(pQuery)) { - qDebug(msg, GET_QINFO_ADDR(pQuery), "only-first stable", pQuery->order.order, TSDB_ORDER_ASC, + qDebug(msg, pQInfo, "only-first stable", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); @@ -2424,7 +2109,7 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo pQuery->order.order = TSDB_ORDER_ASC; } else if (onlyLastQuery(pQuery)) { if (QUERY_IS_ASC_QUERY(pQuery)) { - qDebug(msg, GET_QINFO_ADDR(pQuery), "only-last stable", pQuery->order.order, TSDB_ORDER_DESC, + qDebug(msg, pQInfo, "only-last stable", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); @@ -2437,48 +2122,29 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo } } -static int32_t getInitialPageNum(SQInfo *pQInfo) { - SQuery *pQuery = pQInfo->runtimeEnv.pQuery; - int32_t INITIAL_RESULT_ROWS_VALUE = 16; - - int32_t num = 0; - - if (isGroupbyColumn(pQuery->pGroupbyExpr)) { - num = 128; - } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) { // time window query, allocate one page for each table - size_t s = pQInfo->tableqinfoGroupInfo.numOfTables; - num = (int32_t)(MAX(s, INITIAL_RESULT_ROWS_VALUE)); - } else { // for super table query, one page for each subset - num = 1; // pQInfo->pSidSet->numOfSubSet; - } - - assert(num > 0); - return num; -} - static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) { SQuery* pQuery = pRuntimeEnv->pQuery; int32_t MIN_ROWS_PER_PAGE = 4; - *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery)); + *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery)); int32_t overhead = sizeof(tFilePage); // one page contains at least two rows *ps = DEFAULT_INTERN_BUF_PAGE_SIZE; while(((*rowsize) * MIN_ROWS_PER_PAGE) > (*ps) - overhead) { - *ps = (*ps << 1u); + *ps = ((*ps) << 1u); } - pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize); - assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE); +// pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize); +// assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE); } #define IS_PREFILTER_TYPE(_t) ((_t) != TSDB_DATA_TYPE_BINARY && (_t) != TSDB_DATA_TYPE_NCHAR) -static bool needToLoadDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, - int32_t numOfRows) { +static bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) { SQuery* pQuery = pRuntimeEnv->pQuery; - if (pDataStatis == NULL || (pQuery->numOfFilterCols == 0 && (!pRuntimeEnv->topBotQuery))) { + + if (pDataStatis == NULL || pQuery->numOfFilterCols == 0) { return true; } @@ -2537,15 +2203,6 @@ static bool needToLoadDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDat } } - if (pRuntimeEnv->topBotQuery) { - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - int32_t functionId = pQuery->pExpr1[i].base.functionId; - if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { - return topbot_datablock_filter(&pCtx[i], functionId, (char *)&pDataStatis[i].min, (char *)&pDataStatis[i].max); - } - } - } - return false; } @@ -2598,86 +2255,323 @@ static bool overlapWithTimeWindow(SQuery* pQuery, SDataBlockInfo* pBlockInfo) { return false; } -int32_t loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo * pWindowResInfo, void* pQueryHandle, SDataBlockInfo* pBlockInfo, SDataStatis **pStatis, SArray** pDataBlock, uint32_t* status) { - *status = BLK_DATA_NO_NEEDED; - - SQuery *pQuery = pRuntimeEnv->pQuery; - int64_t groupId = pQuery->current->groupIndex; +static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key, bool ascQuery) { + STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf); - SQueryCostInfo* pCost = &pRuntimeEnv->summary; +#if defined(_DEBUG_VIEW) + printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n", + elem.ts, key, elem.tag.i64, pQuery->order.order, pRuntimeEnv->pTsBuf->tsOrder, + pRuntimeEnv->pTsBuf->cur.order, pRuntimeEnv->pTsBuf->cur.tsIndex); +#endif - if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf > 0) { - *status = BLK_DATA_ALL_NEEDED; - } else { // check if this data block is required to load - // Calculate all time windows that are overlapping or contain current data block. - // If current data block is contained by all possible time window, do not load current data block. - if (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, pBlockInfo)) { - *status = BLK_DATA_ALL_NEEDED; + if (ascQuery) { + if (key < elem.ts) { + return TS_JOIN_TS_NOT_EQUALS; + } else if (key > elem.ts) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN); + } + } else { + if (key > elem.ts) { + return TS_JOIN_TS_NOT_EQUALS; + } else if (key < elem.ts) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN); } + } - if ((*status) != BLK_DATA_ALL_NEEDED) { - // the pCtx[i] result is belonged to previous time window since the outputBuf has not been set yet, - // the filter result may be incorrect. So in case of interval query, we need to set the correct time output buffer - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - SResultRow* pResult = NULL; + return TS_JOIN_TS_EQUAL; +} - bool masterScan = IS_MASTER_SCAN(pRuntimeEnv); +void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, + SSDataBlock* pBlock, STSBuf* pTsBuf, bool ascQuery) { + int32_t numOfRows = pBlock->info.rows; - TSKEY k = QUERY_IS_ASC_QUERY(pQuery)? pBlockInfo->window.skey:pBlockInfo->window.ekey; - STimeWindow win = getActiveTimeWindow(pWindowResInfo, k, pQuery); - if (setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId) != TSDB_CODE_SUCCESS) { - // todo handle error in set result for timewindow - } - } + int8_t *p = calloc(numOfRows, sizeof(int8_t)); + bool all = true; - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SSqlFuncMsg* pSqlFunc = &pQuery->pExpr1[i].base; + if (pTsBuf != NULL) { + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0); - int32_t functionId = pSqlFunc->functionId; - int32_t colId = pSqlFunc->colInfo.colId; - (*status) |= aAggs[functionId].dataReqFunc(&pRuntimeEnv->pCtx[i], pBlockInfo->window.skey, pBlockInfo->window.ekey, colId); - if (((*status) & BLK_DATA_ALL_NEEDED) == BLK_DATA_ALL_NEEDED) { + TSKEY* k = (TSKEY*) pColInfoData->pData; + for (int32_t i = 0; i < numOfRows; ++i) { + int32_t offset = ascQuery? i:(numOfRows - i - 1); + int32_t ret = doTSJoinFilter(pRuntimeEnv, k[offset], ascQuery); + if (ret == TS_JOIN_TAG_NOT_EQUALS) { + break; + } else if (ret == TS_JOIN_TS_NOT_EQUALS) { + all = false; + continue; + } else { + assert(ret == TS_JOIN_TS_EQUAL); + p[offset] = true; + } + + if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) { + break; + } + } + } else { + for (int32_t i = 0; i < numOfRows; ++i) { + bool qualified = false; + + for (int32_t k = 0; k < numOfFilterCols; ++k) { + char* pElem = (char*)pFilterInfo[k].pData + pFilterInfo[k].info.bytes * i; + + qualified = false; + for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) { + SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j]; + + bool isnull = isNull(pElem, pFilterInfo[k].info.type); + if (isnull) { + if (pFilterElem->fp == isNullOperator) { + qualified = true; + break; + } else { + continue; + } + } else { + if (pFilterElem->fp == notNullOperator) { + qualified = true; + break; + } else if (pFilterElem->fp == isNullOperator) { + continue; + } + } + + if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) { + qualified = true; + break; + } + } + + if (!qualified) { break; } } + + p[i] = qualified ? 1 : 0; + if (!qualified) { + all = false; + } + } + } + + if (!all) { + int32_t start = 0; + int32_t len = 0; + for (int32_t j = 0; j < numOfRows; ++j) { + if (p[j] == 1) { + len++; + } else { + if (len > 0) { + int32_t cstart = j - len; + for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) { + SColumnInfoData *pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i); + + int16_t bytes = pColumnInfoData->info.bytes; + memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes); + } + + start += len; + len = 0; + } + } + } + + if (len > 0) { + int32_t cstart = numOfRows - len; + for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) { + SColumnInfoData *pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i); + + int16_t bytes = pColumnInfoData->info.bytes; + memmove(pColumnInfoData->pData + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes); + } + + start += len; + len = 0; + } + + pBlock->info.rows = start; + pBlock->pBlockStatis = NULL; // clean the block statistics info + + if (start > 0) { + SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0); + assert(pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP && + pColumnInfoData->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX); + + pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData; + pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1)); + } + } + + tfree(p); +} + +static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId); +static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes); + +static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSDataBlock* pBlock) { + SQLFunctionCtx* pCtx = pTableScanInfo->pCtx; + uint32_t status = BLK_DATA_NO_NEEDED; + + int32_t numOfOutput = pTableScanInfo->numOfOutput; + for (int32_t i = 0; i < numOfOutput; ++i) { + int32_t functionId = pCtx[i].functionId; + int32_t colId = pTableScanInfo->pExpr[i].base.colInfo.colId; + + // group by + first/last should not apply the first/last block filter + status |= aAggs[functionId].dataReqFunc(&pTableScanInfo->pCtx[i], &pBlock->info.window, colId); + if ((status & BLK_DATA_ALL_NEEDED) == BLK_DATA_ALL_NEEDED) { + return status; + } + } + + return status; +} + +static void doSetFilterColumnInfo(SQuery* pQuery, SSDataBlock* pBlock) { + if (pQuery->numOfFilterCols > 0 && pQuery->pFilterInfo[0].pData != NULL) { + return; + } + + // set the initial static data value filter expression + for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) { + for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) { + SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j); + + if (pQuery->pFilterInfo[i].info.colId == pColInfo->info.colId) { + pQuery->pFilterInfo[i].pData = pColInfo->pData; + break; + } + } + } +} + +int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock, + uint32_t* status) { + *status = BLK_DATA_NO_NEEDED; + pBlock->pDataBlock = NULL; + pBlock->pBlockStatis = NULL; + + SQuery* pQuery = pRuntimeEnv->pQuery; + int64_t groupId = pQuery->current->groupIndex; + bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); + + SQInfo* pQInfo = pRuntimeEnv->qinfo; + SQueryCostInfo* pCost = &pQInfo->summary; + + if (pRuntimeEnv->pTsBuf != NULL) { + (*status) = BLK_DATA_ALL_NEEDED; + + if (pQuery->stableQuery) { // todo refactor + SExprInfo* pExprInfo = &pTableScanInfo->pExpr[0]; + int16_t tagId = (int16_t)pExprInfo->base.arg->argValue.i64; + SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagId); + + // compare tag first + tVariant t = {0}; + doSetTagValueInParam(pQuery->current->pTable, tagId, &t, pColInfo->type, pColInfo->bytes); + setTimestampListJoinInfo(pRuntimeEnv, &t, pQuery->current); + + STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf); + if (!tsBufIsValidElem(&elem) || (tsBufIsValidElem(&elem) && (tVariantCompare(&t, elem.tag) != 0))) { + (*status) = BLK_DATA_DISCARD; + return TSDB_CODE_SUCCESS; + } } } + // Calculate all time windows that are overlapping or contain current data block. + // If current data block is contained by all possible time window, do not load current data block. + if (pQuery->numOfFilterCols > 0 || pQuery->groupbyColumn || + (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info))) { + (*status) = BLK_DATA_ALL_NEEDED; + } + + // check if this data block is required to load + if ((*status) != BLK_DATA_ALL_NEEDED) { + // the pCtx[i] result is belonged to previous time window since the outputBuf has not been set yet, + // the filter result may be incorrect. So in case of interval query, we need to set the correct time output buffer + if (QUERY_IS_INTERVAL_QUERY(pQuery)) { + SResultRow* pResult = NULL; + + bool masterScan = IS_MASTER_SCAN(pRuntimeEnv); + TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey; + + STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQuery); + if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId, + pTableScanInfo->pCtx, pTableScanInfo->numOfOutput, + pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) { + longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); + } + } else if (pQuery->stableQuery && (!isTsCompQuery(pQuery))) { // stable aggregate, not interval aggregate or normal column aggregate + doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, + pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput, + pQuery->current->groupIndex); + } + + (*status) = doFilterByBlockTimeWindow(pTableScanInfo, pBlock); + } + + SDataBlockInfo* pBlockInfo = &pBlock->info; if ((*status) == BLK_DATA_NO_NEEDED) { - qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", GET_QINFO_ADDR(pRuntimeEnv), - pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); + qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, pBlockInfo->window.skey, + pBlockInfo->window.ekey, pBlockInfo->rows); pCost->discardBlocks += 1; } else if ((*status) == BLK_DATA_STATIS_NEEDED) { - // this function never returns error? - tsdbRetrieveDataBlockStatisInfo(pQueryHandle, pStatis); pCost->loadBlockStatis += 1; + tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis); - if (*pStatis == NULL) { // data block statistics does not exist, load data block - *pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL); - pCost->totalCheckedRows += pBlockInfo->rows; + if (pBlock->pBlockStatis == NULL) { // data block statistics does not exist, load data block + pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL); + pCost->totalCheckedRows += pBlock->info.rows; } } else { assert((*status) == BLK_DATA_ALL_NEEDED); // load the data block statistics to perform further filter pCost->loadBlockStatis += 1; - tsdbRetrieveDataBlockStatisInfo(pQueryHandle, pStatis); + tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis); + + if (pQuery->topBotQuery && pBlock->pBlockStatis != NULL) { + bool load = false; + for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { + int32_t functionId = pTableScanInfo->pCtx[i].functionId; + if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { + load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min), + (char*)&(pBlock->pBlockStatis[i].max)); + if (!load) { // current block has been discard due to filter applied + pCost->discardBlocks += 1; + qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, + pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); + (*status) = BLK_DATA_DISCARD; + return TSDB_CODE_SUCCESS; + } + } + } + } - if (!needToLoadDataBlock(pRuntimeEnv, *pStatis, pRuntimeEnv->pCtx, pBlockInfo->rows)) { - // current block has been discard due to filter applied + // current block has been discard due to filter applied + if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) { pCost->discardBlocks += 1; - qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", GET_QINFO_ADDR(pRuntimeEnv), - pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); + qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, pBlockInfo->window.skey, + pBlockInfo->window.ekey, pBlockInfo->rows); (*status) = BLK_DATA_DISCARD; + return TSDB_CODE_SUCCESS; } pCost->totalCheckedRows += pBlockInfo->rows; pCost->loadBlocks += 1; - *pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL); - if (*pDataBlock == NULL) { + pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL); + if (pBlock->pDataBlock == NULL) { return terrno; } + + doSetFilterColumnInfo(pQuery, pBlock); + if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) { + filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, pRuntimeEnv->pTsBuf, + ascQuery); + } } return TSDB_CODE_SUCCESS; @@ -2746,148 +2640,6 @@ int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) { return midPos; } -static void expandBuffer(SQueryRuntimeEnv* pRuntimeEnv, int32_t newSize, void* qinfo) { - SQuery* pQuery = pRuntimeEnv->pQuery; - SResultRec *pRec = &pQuery->rec; - - assert(newSize > 0); - - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - int32_t bytes = pQuery->pExpr1[i].bytes; - - char *tmp = realloc(pQuery->sdata[i], bytes * newSize + sizeof(tFilePage)); - if (tmp == NULL) { - longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); - } else { - memset(tmp + sizeof(tFilePage) + bytes * pRec->rows, 0, (size_t)((newSize - pRec->rows) * bytes)); - pQuery->sdata[i] = (tFilePage *)tmp; - } - } - - pRec->capacity = newSize; - qDebug("QInfo:%p realloc output buffer, new size: %d rows, old:%" PRId64 ", remain:%" PRId64, qinfo, newSize, - pRec->capacity, newSize - pRec->rows); -} - -static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) { - // in case of prj/diff query, ensure the output buffer is sufficient to accommodate the results of current block - SQuery* pQuery = pRuntimeEnv->pQuery; - if (!QUERY_IS_INTERVAL_QUERY(pQuery) && !pRuntimeEnv->groupbyColumn && !isFixedOutputQuery(pRuntimeEnv) && !isTsCompQuery(pQuery)) { - SResultRec *pRec = &pQuery->rec; - - int32_t remain = (int32_t)(pRec->capacity - pRec->rows); - if (remain < numOfRows) { - int32_t newSize = (int32_t)(pRec->capacity + (numOfRows - remain)); - expandBuffer(pRuntimeEnv, newSize, GET_QINFO_ADDR(pRuntimeEnv)); - - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - int32_t bytes = pQuery->pExpr1[i].bytes; - - // set the pCtx output buffer position - pRuntimeEnv->pCtx[i].pOutput = pQuery->sdata[i]->data + pRec->rows * bytes; - - int32_t functionId = pQuery->pExpr1[i].base.functionId; - if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { - pRuntimeEnv->pCtx[i].ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput; - } - } - } - } -} - -static void doSetInitialTimewindow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pBlockInfo) { - SQuery* pQuery = pRuntimeEnv->pQuery; - - if (QUERY_IS_INTERVAL_QUERY(pQuery) && pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL) { - STimeWindow w = TSWINDOW_INITIALIZER; - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - - if (QUERY_IS_ASC_QUERY(pQuery)) { - getAlignQueryTimeWindow(pQuery, pBlockInfo->window.skey, pBlockInfo->window.skey, pQuery->window.ekey, &w); - pWindowResInfo->prevSKey = w.skey; - } else { // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp - getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, pQuery->window.ekey, pBlockInfo->window.ekey, &w); - pWindowResInfo->prevSKey = w.skey; - } - } -} - -static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - STableQueryInfo* pTableQueryInfo = pQuery->current; - SQueryCostInfo* summary = &pRuntimeEnv->summary; - - qDebug("QInfo:%p query start, qrange:%" PRId64 "-%" PRId64 ", lastkey:%" PRId64 ", order:%d", - GET_QINFO_ADDR(pRuntimeEnv), pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, pTableQueryInfo->lastKey, - pQuery->order.order); - - TsdbQueryHandleT pQueryHandle = IS_MASTER_SCAN(pRuntimeEnv)? pRuntimeEnv->pQueryHandle : pRuntimeEnv->pSecQueryHandle; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - - SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; - while (tsdbNextDataBlock(pQueryHandle)) { - summary->totalBlocks += 1; - - if (IS_MASTER_SCAN(pRuntimeEnv)) { - pQuery->numOfCheckedBlocks += 1; - } - - if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) { - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } - - tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo); - doSetInitialTimewindow(pRuntimeEnv, &blockInfo); - - // in case of prj/diff query, ensure the output buffer is sufficient to accommodate the results of current block - ensureOutputBuffer(pRuntimeEnv, blockInfo.rows); - - SDataStatis *pStatis = NULL; - SArray * pDataBlock = NULL; - uint32_t status = 0; - - int32_t ret = loadDataBlockOnDemand(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, pQueryHandle, &blockInfo, &pStatis, &pDataBlock, &status); - if (ret != TSDB_CODE_SUCCESS) { - break; - } - - if (status == BLK_DATA_DISCARD) { - pQuery->current->lastKey = - QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step; - continue; - } - - // query start position can not move into tableApplyFunctionsOnBlock due to limit/offset condition - pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0 : blockInfo.rows - 1; - int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, binarySearchForKey, pDataBlock); - - summary->totalRows += blockInfo.rows; - qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QINFO_ADDR(pRuntimeEnv), - blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, numOfRes, pQuery->current->lastKey); - - // while the output buffer is full or limit/offset is applied, query may be paused here - if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL | QUERY_COMPLETED)) { - break; - } - } - - if (terrno != TSDB_CODE_SUCCESS) { - longjmp(pRuntimeEnv->env, terrno); - } - - // if the result buffer is not full, set the query complete - if (!Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)) { - setQueryStatus(pQuery, QUERY_COMPLETED); - } - - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - closeAllResultRows(&pRuntimeEnv->resultRowInfo); - pRuntimeEnv->resultRowInfo.curIndex = pRuntimeEnv->resultRowInfo.size - 1; // point to the last time window - } - - return 0; -} - /* * set tag value in SQLFunctionCtx * e.g.,tag information into input buffer @@ -2895,33 +2647,23 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes) { tVariantDestroy(tag); + char* val = NULL; if (tagColId == TSDB_TBNAME_COLUMN_INDEX) { - char* val = tsdbGetTableName(pTable); + val = tsdbGetTableName(pTable); assert(val != NULL); - - tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), TSDB_DATA_TYPE_BINARY); } else { - char* val = tsdbGetTableTagVal(pTable, tagColId, type, bytes); - if (val == NULL) { - tag->nType = TSDB_DATA_TYPE_NULL; - return; - } - - if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - if (isNull(val, type)) { - tag->nType = TSDB_DATA_TYPE_NULL; - return; - } + val = tsdbGetTableTagVal(pTable, tagColId, type, bytes); + } - tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type); - } else { - if (isNull(val, type)) { - tag->nType = TSDB_DATA_TYPE_NULL; - return; - } + if (val == NULL || isNull(val, type)) { + tag->nType = TSDB_DATA_TYPE_NULL; + return; + } - tVariantCreateFromBinary(tag, val, bytes, type); - } + if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type); + } else { + tVariantCreateFromBinary(tag, val, bytes, type); } } @@ -2937,24 +2679,28 @@ static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t num return NULL; } -void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable) { - SQuery *pQuery = pRuntimeEnv->pQuery; - SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv); +void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) { + SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv; - SExprInfo *pExprInfo = &pQuery->pExpr1[0]; - if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pRuntimeEnv->stableQuery) { + SExprInfo *pExpr = pOperatorInfo->pExpr; + SQuery *pQuery = pRuntimeEnv->pQuery; + + SExprInfo* pExprInfo = &pExpr[0]; + if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pQuery->stableQuery) { assert(pExprInfo->base.numOfParams == 1); - int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; + int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); - doSetTagValueInParam(pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes); + doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes); + return; } else { // set tag value, by which the results are aggregated. int32_t offset = 0; memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen); - for (int32_t idx = 0; idx < pQuery->numOfOutput; ++idx) { - SExprInfo* pLocalExprInfo = &pQuery->pExpr1[idx]; + + for (int32_t idx = 0; idx < numOfOutput; ++idx) { + SExprInfo* pLocalExprInfo = &pExpr[idx]; // ts_comp column required the tag value for join filter if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.colInfo.flag)) { @@ -2962,39 +2708,28 @@ void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable) { } // todo use tag column index to optimize performance - doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pRuntimeEnv->pCtx[idx].tag, - pLocalExprInfo->type, pLocalExprInfo->bytes); + doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type, + pLocalExprInfo->bytes); if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) { - memcpy(pRuntimeEnv->tagVal + offset, &pRuntimeEnv->pCtx[idx].tag.i64, pLocalExprInfo->bytes); + memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes); } else { - memcpy(pRuntimeEnv->tagVal + offset, pRuntimeEnv->pCtx[idx].tag.pz, pRuntimeEnv->pCtx[idx].tag.nLen); + memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen); } offset += pLocalExprInfo->bytes; } - // set the join tag for first column - SSqlFuncMsg *pFuncMsg = &pExprInfo->base; - if ((pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) && pRuntimeEnv->pTsBuf != NULL && - pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { - assert(pFuncMsg->numOfParams == 1); - - int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; - SColumnInfo *pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); - - doSetTagValueInParam(pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes); - - int16_t tagType = pRuntimeEnv->pCtx[0].tag.nType; - if (tagType == TSDB_DATA_TYPE_BINARY || tagType == TSDB_DATA_TYPE_NCHAR) { - qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%s", pQInfo, - pExprInfo->base.arg->argValue.i64, pRuntimeEnv->pCtx[0].tag.pz); - } else { - qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pQInfo, - pExprInfo->base.arg->argValue.i64, pRuntimeEnv->pCtx[0].tag.i64); - } + //todo : use index to avoid iterator all possible output columns + if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) { + setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo); } } + + // set the tsBuf start position before check each data block + if (pRuntimeEnv->pTsBuf != NULL) { + setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable); + } } static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) { @@ -3100,35 +2835,36 @@ void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntim } } -static int32_t doCopyToSData(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType); - -void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { - SGroupResInfo* pGroupResInfo = &pQInfo->groupResInfo; +void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) { + SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo; + pBlock->info.rows = 0; - while(pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) { + int32_t code = TSDB_CODE_SUCCESS; + while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) { // all results in current group have been returned to client, try next group if ((pGroupResInfo->pRows == NULL) || taosArrayGetSize(pGroupResInfo->pRows) == 0) { assert(pGroupResInfo->index == 0); - if ((pQInfo->code = mergeIntoGroupResult(&pQInfo->groupResInfo, pQInfo)) != TSDB_CODE_SUCCESS) { + if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) { return; } } - pQuery->rec.rows = doCopyToSData(&pQInfo->runtimeEnv, pGroupResInfo, TSDB_ORDER_ASC); + doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock); // current data are all dumped to result buffer, clear it - if (!hasRemainData(pGroupResInfo)) { + if (!hasRemainDataInCurrentGroup(pGroupResInfo)) { cleanupGroupResInfo(pGroupResInfo); if (!incNextGroup(pGroupResInfo)) { - SET_STABLE_QUERY_OVER(pQInfo); + break; } } - // enough results in data buffer, return - if (pQuery->rec.rows >= pQuery->rec.threshold) { - break; + // enough results in data buffer, return + if (pBlock->info.rows >= threshold) { + break; + } } - } + } static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) { @@ -3142,71 +2878,17 @@ static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo * SWITCH_ORDER(pTableQueryInfo->cur.order); pTableQueryInfo->cur.vgroupIndex = -1; - // set the index at the end of time window + // set the index to be the end slot of result rows array pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1; } -static void disableFuncInReverseScanImpl(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo *pWindowResInfo, int32_t order) { +static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) { SQuery* pQuery = pRuntimeEnv->pQuery; - for (int32_t i = 0; i < pWindowResInfo->size; ++i) { - bool closed = getResultRowStatus(pWindowResInfo, i); - if (!closed) { - continue; - } - - SResultRow *pRow = getResultRow(pWindowResInfo, i); - - // open/close the specified query for each group result - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int32_t functId = pQuery->pExpr1[j].base.functionId; - SResultRowCellInfo* pInfo = getResultCell(pRuntimeEnv, pRow, j); - - if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSDB_ORDER_ASC) || - ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSDB_ORDER_DESC)) { - pInfo->complete = false; - } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) { - pInfo->complete = true; - } - } - } -} - -void disableFuncInReverseScan(SQInfo *pQInfo) { - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery *pQuery = pRuntimeEnv->pQuery; - int32_t order = pQuery->order.order; - - // group by normal columns and interval query on normal table - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - if (pRuntimeEnv->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) { - disableFuncInReverseScanImpl(pRuntimeEnv, pWindowResInfo, order); - } else { // for simple result of table query, - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { // todo refactor - int32_t functId = pQuery->pExpr1[j].base.functionId; - - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[j]; - if (pCtx->resultInfo == NULL) { - continue; // resultInfo is NULL, means no data checked in previous scan - } - - if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSDB_ORDER_ASC) || - ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSDB_ORDER_DESC)) { - pCtx->resultInfo->complete = false; - } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) { - pCtx->resultInfo->complete = true; - } - } - } -} - -static void setupQueryRangeForReverseScan(SQInfo* pQInfo) { - SQuery* pQuery = pQInfo->runtimeEnv.pQuery; - int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); - + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv)); for(int32_t i = 0; i < numOfGroups; ++i) { - SArray *group = GET_TABLEGROUP(pQInfo, i); - SArray *tableKeyGroup = taosArrayGetP(pQInfo->tableGroupInfo.pGroupList, i); + SArray *group = GET_TABLEGROUP(pRuntimeEnv, i); + SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i); size_t t = taosArrayGetSize(group); for (int32_t j = 0; j < t; ++j) { @@ -3223,209 +2905,117 @@ static void setupQueryRangeForReverseScan(SQInfo* pQInfo) { } } -void switchCtxOrder(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SWITCH_ORDER(pRuntimeEnv->pCtx[i].order); +void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) { + for (int32_t i = 0; i < numOfOutput; ++i) { + SWITCH_ORDER(pCtx[i].order); } } int32_t initResultRow(SResultRow *pResultRow) { pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow)); pResultRow->pageId = -1; - pResultRow->rowId = -1; + pResultRow->offset = -1; return TSDB_CODE_SUCCESS; } -void resetDefaultResInfoOutputBuf(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; +/* + * The start of each column SResultRowCellInfo is denote by RowCellInfoOffset. + * Note that in case of top/bottom query, the whole multiple rows of result is treated as only one row of results. + * +------------+-----------------result column 1-----------+-----------------result column 2-----------+ + * + SResultRow | SResultRowCellInfo | intermediate buffer1 | SResultRowCellInfo | intermediate buffer 2| + * +------------+-------------------------------------------+-------------------------------------------+ + * offset[0] offset[1] + */ +void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid) { + SQLFunctionCtx* pCtx = pInfo->pCtx; + SSDataBlock* pDataBlock = pInfo->pRes; + int32_t* rowCellInfoOffset = pInfo->rowCellInfoOffset; + SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo; int32_t tid = 0; - int64_t uid = 0; - SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, (char *)&tid, sizeof(tid), true, uid); + SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid); - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; - pCtx->pOutput = pQuery->sdata[i]->data; + for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { + SColumnInfoData* pData = taosArrayGet(pDataBlock->pDataBlock, i); /* * set the output buffer information and intermediate buffer * not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc. */ - SResultRowCellInfo* pCellInfo = getResultCell(pRuntimeEnv, pRow, i); + SResultRowCellInfo* pCellInfo = getResultCell(pRow, i, rowCellInfoOffset); RESET_RESULT_INFO(pCellInfo); - pCtx->resultInfo = pCellInfo; + + pCtx[i].resultInfo = pCellInfo; + pCtx[i].pOutput = pData->pData; + assert(pCtx[i].pOutput != NULL); // set the timestamp output buffer for top/bottom/diff query - int32_t functionId = pQuery->pExpr1[i].base.functionId; + int32_t functionId = pCtx[i].functionId; if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { - pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput; + pCtx[i].ptsOutputBuf = pCtx[0].pOutput; } - - memset(pQuery->sdata[i]->data, 0, (size_t)(pQuery->pExpr1[i].bytes * pQuery->rec.capacity)); } - initCtxOutputBuf(pRuntimeEnv); + initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols); } -void forwardCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, int64_t output) { - SQuery *pQuery = pRuntimeEnv->pQuery; +void updateOutputBuf(SArithOperatorInfo* pInfo, int32_t numOfInputRows) { + SOptrBasicInfo* pBInfo = &pInfo->binfo; + SSDataBlock* pDataBlock = pBInfo->pRes; - // reset the execution contexts - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int32_t functionId = pQuery->pExpr1[j].base.functionId; - assert(functionId != TSDB_FUNC_DIFF); + int32_t newSize = pDataBlock->info.rows + numOfInputRows; + if (pInfo->bufCapacity < newSize) { + for(int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { + SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i); + char* p = realloc(pColInfo->pData, newSize * pColInfo->info.bytes); + if (p != NULL) { + pColInfo->pData = p; - // set next output position - if (IS_OUTER_FORWARD(aAggs[functionId].status)) { - pRuntimeEnv->pCtx[j].pOutput += pRuntimeEnv->pCtx[j].outputBytes * output; + // it starts from the tail of the previously generated results. + pBInfo->pCtx[i].pOutput = pColInfo->pData; + pInfo->bufCapacity = newSize; + } else { + // longjmp + } } + } - if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { - /* - * NOTE: for top/bottom query, the value of first column of output (timestamp) are assigned - * in the procedure of top/bottom routine - * the output buffer in top/bottom routine is ptsOutputBuf, so we need to forward the output buffer - * - * diff function is handled in multi-output function - */ - pRuntimeEnv->pCtx[j].ptsOutputBuf = (char*)pRuntimeEnv->pCtx[j].ptsOutputBuf + TSDB_KEYSIZE * output; - } + for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { + SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i); + pBInfo->pCtx[i].pOutput = pColInfo->pData + pColInfo->info.bytes * pDataBlock->info.rows; - RESET_RESULT_INFO(pRuntimeEnv->pCtx[j].resultInfo); + // re-estabilish output buffer pointer. + int32_t functionId = pBInfo->pCtx[i].functionId; + if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { + pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[0].pOutput; + } } } -void initCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int32_t functionId = pQuery->pExpr1[j].base.functionId; - pRuntimeEnv->pCtx[j].currentStage = 0; - - SResultRowCellInfo* pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]); +void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) { + for (int32_t j = 0; j < size; ++j) { + SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]); if (pResInfo->initialized) { continue; } - aAggs[functionId].init(&pRuntimeEnv->pCtx[j]); + aAggs[pCtx[j].functionId].init(&pCtx[j]); } } -void skipResults(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - if (pQuery->rec.rows == 0 || pQuery->limit.offset == 0) { - return; - } - - if (pQuery->rec.rows <= pQuery->limit.offset) { - qDebug("QInfo:%p skip rows:%" PRId64 ", new offset:%" PRIu64, GET_QINFO_ADDR(pRuntimeEnv), pQuery->rec.rows, - pQuery->limit.offset - pQuery->rec.rows); - - pQuery->limit.offset -= pQuery->rec.rows; - pQuery->rec.rows = 0; - - resetDefaultResInfoOutputBuf(pRuntimeEnv); - - // clear the buffer full flag if exists - CLEAR_QUERY_STATUS(pQuery, QUERY_RESBUF_FULL); - } else { - int64_t numOfSkip = pQuery->limit.offset; - pQuery->rec.rows -= numOfSkip; - pQuery->limit.offset = 0; - - qDebug("QInfo:%p skip row:%"PRId64", new offset:%d, numOfRows remain:%" PRIu64, GET_QINFO_ADDR(pRuntimeEnv), numOfSkip, - 0, pQuery->rec.rows); - - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - int32_t functionId = pQuery->pExpr1[i].base.functionId; - int32_t bytes = pRuntimeEnv->pCtx[i].outputBytes; - - memmove(pQuery->sdata[i]->data, (char*)pQuery->sdata[i]->data + bytes * numOfSkip, (size_t)(pQuery->rec.rows * bytes)); - pRuntimeEnv->pCtx[i].pOutput = ((char*) pQuery->sdata[i]->data) + pQuery->rec.rows * bytes; - - if (functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { - pRuntimeEnv->pCtx[i].ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput; - } - } - - updateNumOfResult(pRuntimeEnv, (int32_t)pQuery->rec.rows); - } -} - -void setQueryStatus(SQuery *pQuery, int8_t status) { +void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) { if (status == QUERY_NOT_COMPLETED) { - pQuery->status = status; + pRuntimeEnv->status = status; } else { // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first - CLEAR_QUERY_STATUS(pQuery, QUERY_NOT_COMPLETED); - pQuery->status |= status; - } -} - -bool needRepeatScan(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - bool toContinue = false; - if (pRuntimeEnv->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) { - // for each group result, call the finalize function for each column - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - - for (int32_t i = 0; i < pWindowResInfo->size; ++i) { - SResultRow *pResult = getResultRow(pWindowResInfo, i); - - setResultOutputBuf(pRuntimeEnv, pResult); - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int16_t functId = pQuery->pExpr1[j].base.functionId; - if (functId == TSDB_FUNC_TS) { - continue; - } - - aAggs[functId].xNextStep(&pRuntimeEnv->pCtx[j]); - SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]); - - toContinue |= (!pResInfo->complete); - } - } - } else { - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int16_t functId = pQuery->pExpr1[j].base.functionId; - if (functId == TSDB_FUNC_TS) { - continue; - } - - aAggs[functId].xNextStep(&pRuntimeEnv->pCtx[j]); - SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]); - - toContinue |= (!pResInfo->complete); - } + CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED); + pRuntimeEnv->status |= status; } - - return toContinue; -} - -static SQueryStatusInfo getQueryStatusInfo(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) { - SQuery *pQuery = pRuntimeEnv->pQuery; - STableQueryInfo* pTableQueryInfo = pQuery->current; - - assert((start <= pTableQueryInfo->lastKey && QUERY_IS_ASC_QUERY(pQuery)) || - (start >= pTableQueryInfo->lastKey && !QUERY_IS_ASC_QUERY(pQuery))); - - SQueryStatusInfo info = { - .status = pQuery->status, - .windowIndex = pRuntimeEnv->resultRowInfo.curIndex, - .lastKey = start, - }; - - TIME_WINDOW_COPY(info.w, pQuery->window); - return info; } -static void setEnvBeforeReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusInfo *pStatus) { - SQInfo *pQInfo = GET_QINFO_ADDR(pRuntimeEnv); +static void setupEnvForReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, SQLFunctionCtx* pCtx, int32_t numOfOutput) { SQuery *pQuery = pRuntimeEnv->pQuery; - pStatus->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); // save the cursor if (pRuntimeEnv->pTsBuf) { SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order); bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf); @@ -3434,228 +3024,49 @@ static void setEnvBeforeReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusI // reverse order time range SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); - SWITCH_ORDER(pQuery->order.order); - - if (QUERY_IS_ASC_QUERY(pQuery)) { - assert(pQuery->window.skey <= pQuery->window.ekey); - } else { - assert(pQuery->window.skey >= pQuery->window.ekey); - } SET_REVERSE_SCAN_FLAG(pRuntimeEnv); - STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); - - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); - switchCtxOrder(pRuntimeEnv); - disableFuncInReverseScan(pQInfo); - setupQueryRangeForReverseScan(pQInfo); - - // clean unused handle - if (pRuntimeEnv->pSecQueryHandle != NULL) { - tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); - } - - pRuntimeEnv->pSecQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); - if (pRuntimeEnv->pSecQueryHandle == NULL) { - longjmp(pRuntimeEnv->env, terrno); - } -} - -static void clearEnvAfterReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusInfo *pStatus) { - SQuery *pQuery = pRuntimeEnv->pQuery; - STableQueryInfo* pTableQueryInfo = pQuery->current; + setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED); + switchCtxOrder(pCtx, numOfOutput); SWITCH_ORDER(pQuery->order.order); - switchCtxOrder(pRuntimeEnv); - - tsBufSetCursor(pRuntimeEnv->pTsBuf, &pStatus->cur); - if (pRuntimeEnv->pTsBuf) { - pRuntimeEnv->pTsBuf->cur.order = pQuery->order.order; - } - - SET_MASTER_SCAN_FLAG(pRuntimeEnv); - - // update the pQuery->window.skey and pQuery->window.ekey to limit the scan scope of sliding query during reverse scan - pTableQueryInfo->lastKey = pStatus->lastKey; - pQuery->status = pStatus->status; - - pTableQueryInfo->win = pStatus->w; - pQuery->window = pTableQueryInfo->win; -} - -static void restoreTimeWindow(STableGroupInfo* pTableGroupInfo, STsdbQueryCond* pCond) { - assert(pTableGroupInfo->numOfTables == 1); - SArray* pTableKeyGroup = taosArrayGetP(pTableGroupInfo->pGroupList, 0); - STableKeyInfo* pKeyInfo = taosArrayGet(pTableKeyGroup, 0); - pKeyInfo->lastKey = pCond->twindow.skey; -} - -static void handleInterpolationQuery(SQInfo* pQInfo) { - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - - SQuery *pQuery = pRuntimeEnv->pQuery; - if (pQuery->numOfCheckedBlocks > 0 || !isPointInterpoQuery(pQuery)) { - return; - } - - SArray *prev = tsdbGetExternalRow(pRuntimeEnv->pQueryHandle, &pQInfo->memRef, TSDB_PREV_ROW); - SArray *next = tsdbGetExternalRow(pRuntimeEnv->pQueryHandle, &pQInfo->memRef, TSDB_NEXT_ROW); - if (prev == NULL || next == NULL) { - return; - } - - // setup the pCtx->start/end info and calculate the interpolation value - SColumnInfoData *startTs = taosArrayGet(prev, 0); - SColumnInfoData *endTs = taosArrayGet(next, 0); - - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; - - int32_t functionId = pQuery->pExpr1[i].base.functionId; - SColIndex *pColIndex = &pQuery->pExpr1[i].base.colInfo; - - if (!TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) { - aAggs[functionId].xFunction(pCtx); - continue; - } - - SColumnInfoData *p = taosArrayGet(prev, pColIndex->colIndex); - SColumnInfoData *n = taosArrayGet(next, pColIndex->colIndex); - - assert(p->info.colId == pColIndex->colId); - - pCtx->start.key = *(TSKEY *)startTs->pData; - pCtx->end.key = *(TSKEY *)endTs->pData; - - if (p->info.type != TSDB_DATA_TYPE_BINARY && p->info.type != TSDB_DATA_TYPE_NCHAR) { - GET_TYPED_DATA(pCtx->start.val, double, p->info.type, p->pData); - GET_TYPED_DATA(pCtx->end.val, double, n->info.type, n->pData); - } else { // string pointer - pCtx->start.ptr = p->pData; - pCtx->end.ptr = n->pData; - } - - pCtx->param[2].i64 = (int8_t)pQuery->fillType; - pCtx->startTs = pQuery->window.skey; - if (pQuery->fillVal != NULL) { - if (isNull((const char *)&pQuery->fillVal[i], pCtx->inputType)) { - pCtx->param[1].nType = TSDB_DATA_TYPE_NULL; - } else { // todo refactor, tVariantCreateFromBinary should handle the NULL value - if (pCtx->inputType != TSDB_DATA_TYPE_BINARY && pCtx->inputType != TSDB_DATA_TYPE_NCHAR) { - tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQuery->fillVal[i], pCtx->inputBytes, pCtx->inputType); - } - } - } - - aAggs[functionId].xFunction(pCtx); - } -} - -void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) { - SQInfo *pQInfo = (SQInfo *) GET_QINFO_ADDR(pRuntimeEnv); - SQuery *pQuery = pRuntimeEnv->pQuery; - STableQueryInfo *pTableQueryInfo = pQuery->current; - - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); - - // store the start query position - SQueryStatusInfo qstatus = getQueryStatusInfo(pRuntimeEnv, start); - SET_MASTER_SCAN_FLAG(pRuntimeEnv); - - if (!pRuntimeEnv->groupbyColumn && pRuntimeEnv->hasTagResults) { - setTagVal(pRuntimeEnv, pTableQueryInfo->pTable); - } - - while (1) { - doScanAllDataBlocks(pRuntimeEnv); - - if (pRuntimeEnv->scanFlag == MASTER_SCAN) { - qstatus.status = pQuery->status; - - // do nothing if no data blocks are found qualified during scan - if (qstatus.lastKey == pTableQueryInfo->lastKey) { - qDebug("QInfo:%p no results generated in this scan", pQInfo); - } - } - - if (!needRepeatScan(pRuntimeEnv)) { - // restore the status code and jump out of loop - if (pRuntimeEnv->scanFlag == REPEAT_SCAN) { - pQuery->status = qstatus.status; - } - - break; - } - - if (pRuntimeEnv->pSecQueryHandle != NULL) { - tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); - } - - STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); - restoreTimeWindow(&pQInfo->tableGroupInfo, &cond); - pRuntimeEnv->pSecQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); - if (pRuntimeEnv->pSecQueryHandle == NULL) { - longjmp(pRuntimeEnv->env, terrno); - } - - pRuntimeEnv->resultRowInfo.curIndex = qstatus.windowIndex; - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); - pRuntimeEnv->scanFlag = REPEAT_SCAN; - - if (pRuntimeEnv->pTsBuf) { - bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf); - assert(ret); - } - - qDebug("QInfo:%p start to repeat scan data blocks due to query func required, qrange:%"PRId64"-%"PRId64, pQInfo, - cond.twindow.skey, cond.twindow.ekey); - } - if (needReverseScan(pQuery)) { - setEnvBeforeReverseScan(pRuntimeEnv, &qstatus); - - // reverse scan from current position - qDebug("QInfo:%p start to reverse scan", pQInfo); - doScanAllDataBlocks(pRuntimeEnv); - - clearEnvAfterReverseScan(pRuntimeEnv, &qstatus); - } - - handleInterpolationQuery(pQInfo); + setupQueryRangeForReverseScan(pRuntimeEnv); } -void finalizeQueryResult(SQueryRuntimeEnv *pRuntimeEnv) { +void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) { + SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv; SQuery *pQuery = pRuntimeEnv->pQuery; - if (pRuntimeEnv->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) { + int32_t numOfOutput = pOperator->numOfOutput; + if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) { // for each group result, call the finalize function for each column - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - if (pRuntimeEnv->groupbyColumn) { - closeAllResultRows(pWindowResInfo); + if (pQuery->groupbyColumn) { + closeAllResultRows(pResultRowInfo); } - for (int32_t i = 0; i < pWindowResInfo->size; ++i) { - SResultRow *buf = pWindowResInfo->pResult[i]; - if (!isResultRowClosed(pWindowResInfo, i)) { + for (int32_t i = 0; i < pResultRowInfo->size; ++i) { + SResultRow *buf = pResultRowInfo->pResult[i]; + if (!isResultRowClosed(pResultRowInfo, i)) { continue; } - setResultOutputBuf(pRuntimeEnv, buf); + setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset); - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - aAggs[pQuery->pExpr1[j].base.functionId].xFinalize(&pRuntimeEnv->pCtx[j]); + for (int32_t j = 0; j < numOfOutput; ++j) { + aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); } /* * set the number of output results for group by normal columns, the number of output rows usually is 1 except * the top and bottom query */ - buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv); + buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput); } } else { - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - aAggs[pQuery->pExpr1[j].base.functionId].xFinalize(&pRuntimeEnv->pCtx[j]); + for (int32_t j = 0; j < numOfOutput; ++j) { + aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); } } } @@ -3703,25 +3114,40 @@ void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) { cleanupResultRowInfo(&pTableQueryInfo->resInfo); } -/** - * set output buffer for different group - * @param pRuntimeEnv - * @param pDataBlockInfo - */ -void setExecutionContext(SQInfo *pQInfo, int32_t groupIndex, TSKEY nextKey) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - STableQueryInfo *pTableQueryInfo = pRuntimeEnv->pQuery->current; - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; +void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, + int32_t numOfOutput, int32_t* rowCellInfoOffset) { + // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group + tFilePage* bufPage = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId); - // lastKey needs to be updated - pTableQueryInfo->lastKey = nextKey; - if (pRuntimeEnv->prevGroupId != INT32_MIN && pRuntimeEnv->prevGroupId == groupIndex) { - return; + int16_t offset = 0; + for (int32_t i = 0; i < numOfOutput; ++i) { + pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset); + + SResultRowCellInfo* pResInfo = pCtx[i].resultInfo; + if (pResInfo->initialized && pResInfo->complete) { + offset += pCtx[i].outputBytes; + continue; + } + + pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, bufPage, pResult->offset, offset); + offset += pCtx[i].outputBytes; + + int32_t functionId = pCtx[i].functionId; + if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { + pCtx[i].ptsOutputBuf = pCtx[0].pOutput; + } + + if (!pResInfo->initialized) { + aAggs[functionId].init(&pCtx[i]); + } } +} +void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx, + int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) { int64_t uid = 0; - SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pWindowResInfo, (char *)&groupIndex, - sizeof(groupIndex), true, uid); + SResultRow* pResultRow = + doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid); assert (pResultRow != NULL); /* @@ -3729,142 +3155,146 @@ void setExecutionContext(SQInfo *pQInfo, int32_t groupIndex, TSKEY nextKey) { * all group belong to one result set, and each group result has different group id so set the id to be one */ if (pResultRow->pageId == -1) { - if (addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->numOfRowsPerPage) != - TSDB_CODE_SUCCESS) { + int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize); + if (ret != TSDB_CODE_SUCCESS) { return; } } + setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset); +} + +void setExecutionContext(SQueryRuntimeEnv* pRuntimeEnv, SOptrBasicInfo* pInfo, int32_t numOfOutput, int32_t groupIndex, + TSKEY nextKey) { + STableQueryInfo *pTableQueryInfo = pRuntimeEnv->pQuery->current; + + // lastKey needs to be updated + pTableQueryInfo->lastKey = nextKey; + if (pRuntimeEnv->prevGroupId != INT32_MIN && pRuntimeEnv->prevGroupId == groupIndex) { + return; + } + + doSetTableGroupOutputBuf(pRuntimeEnv, &pInfo->resultRowInfo, pInfo->pCtx, pInfo->rowCellInfoOffset, numOfOutput, groupIndex); + // record the current active group id pRuntimeEnv->prevGroupId = groupIndex; - setResultOutputBuf(pRuntimeEnv, pResultRow); - initCtxOutputBuf(pRuntimeEnv); } -void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) { - SQuery *pQuery = pRuntimeEnv->pQuery; - +void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, + int32_t numOfCols, int32_t* rowCellInfoOffset) { // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId); - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; - pCtx->pOutput = getPosInResultPage(pRuntimeEnv, i, pResult, page); + int16_t offset = 0; + for (int32_t i = 0; i < numOfCols; ++i) { + pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, page, pResult->offset, offset); + offset += pCtx[i].outputBytes; - int32_t functionId = pQuery->pExpr1[i].base.functionId; + int32_t functionId = pCtx[i].functionId; if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { - pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput; + pCtx[i].ptsOutputBuf = pCtx[0].pOutput; } /* * set the output buffer information and intermediate buffer, * not all queries require the interResultBuf, such as COUNT */ - pCtx->resultInfo = getResultCell(pRuntimeEnv, pResult, i); + pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset); } } -void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group - tFilePage* bufPage = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId); +void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable) { + SQuery* pQuery = pRuntimeEnv->pQuery; - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; + SSqlFuncMsg* pFuncMsg = &pExprInfo->base; + if (pQuery->stableQuery && (pRuntimeEnv->pTsBuf != NULL) && + (pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) && + (pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX)) { + assert(pFuncMsg->numOfParams == 1); - pCtx->resultInfo = getResultCell(pRuntimeEnv, pResult, i); - if (pCtx->resultInfo->initialized && pCtx->resultInfo->complete) { - continue; - } + int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; + SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); - pCtx->pOutput = getPosInResultPage(pRuntimeEnv, i, pResult, bufPage); - pCtx->currentStage = 0; + doSetTagValueInParam(pTable, tagColId, &pCtx->tag, pColInfo->type, pColInfo->bytes); - int32_t functionId = pCtx->functionId; - if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { - pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput; - } - - if (!pCtx->resultInfo->initialized) { - aAggs[functionId].init(pCtx); + int16_t tagType = pCtx[0].tag.nType; + if (tagType == TSDB_DATA_TYPE_BINARY || tagType == TSDB_DATA_TYPE_NCHAR) { + qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%s", pRuntimeEnv->qinfo, + pExprInfo->base.arg->argValue.i64, pCtx[0].tag.pz); + } else { + qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pRuntimeEnv->qinfo, + pExprInfo->base.arg->argValue.i64, pCtx[0].tag.i64); } } } -int32_t setTimestampListJoinInfo(SQInfo *pQInfo, STableQueryInfo *pTableQueryInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; +int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo) { + SQuery* pQuery = pRuntimeEnv->pQuery; + assert(pRuntimeEnv->pTsBuf != NULL); // both the master and supplement scan needs to set the correct ts comp start position - tVariant* pTag = &pRuntimeEnv->pCtx[0].tag; - if (pTableQueryInfo->cur.vgroupIndex == -1) { tVariantAssign(&pTableQueryInfo->tag, pTag); - STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQInfo->vgId, &pTableQueryInfo->tag); + STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQuery->vgId, &pTableQueryInfo->tag); // failed to find data with the specified tag value and vnodeId if (!tsBufIsValidElem(&elem)) { if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qError("QInfo:%p failed to find tag:%s in ts_comp", pQInfo, pTag->pz); + qError("QInfo:%p failed to find tag:%s in ts_comp", pRuntimeEnv->qinfo, pTag->pz); } else { - qError("QInfo:%p failed to find tag:%" PRId64 " in ts_comp", pQInfo, pTag->i64); + qError("QInfo:%p failed to find tag:%" PRId64 " in ts_comp", pRuntimeEnv->qinfo, pTag->i64); } - return false; + return -1; } - // keep the cursor info of current meter + // Keep the cursor info of current table pTableQueryInfo->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); + qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); } else { - qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); + qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); } } else { tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur); - if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); + qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); } else { - qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); + qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex); } } return 0; } -int32_t setParamValue(SQueryRuntimeEnv* pRuntimeEnv) { +void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr) { SQuery* pQuery = pRuntimeEnv->pQuery; - if (pRuntimeEnv->prevResult == NULL || pRuntimeEnv->groupbyColumn) { - return TSDB_CODE_SUCCESS; - } - int32_t numOfExprs = pQuery->numOfOutput; for(int32_t i = 0; i < numOfExprs; ++i) { - SExprInfo* pExprInfo = &(pQuery->pExpr1[i]); - if(pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) { + SExprInfo* pExprInfo = &(pExpr[i]); + if (pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) { continue; } SSqlFuncMsg* pFuncMsg = &pExprInfo->base; - pRuntimeEnv->pCtx[i].param[0].arr = NULL; - pRuntimeEnv->pCtx[i].param[0].nType = TSDB_DATA_TYPE_INT; // avoid freeing the memory by setting the type to be int + pCtx[i].param[0].arr = NULL; + pCtx[i].param[0].nType = TSDB_DATA_TYPE_INT; // avoid freeing the memory by setting the type to be int - int32_t numOfGroup = (int32_t) taosArrayGetSize(pRuntimeEnv->prevResult); - for(int32_t j = 0; j < numOfGroup; ++j) { - SInterResult *p = taosArrayGet(pRuntimeEnv->prevResult, j); + // TODO use hash to speedup this loop + int32_t numOfGroup = (int32_t)taosArrayGetSize(pRuntimeEnv->prevResult); + for (int32_t j = 0; j < numOfGroup; ++j) { + SInterResult* p = taosArrayGet(pRuntimeEnv->prevResult, j); if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) { - - int32_t numOfCols = (int32_t) taosArrayGetSize(p->pResult); - for(int32_t k = 0; k < numOfCols; ++k) { + int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult); + for (int32_t k = 0; k < numOfCols; ++k) { SStddevInterResult* pres = taosArrayGet(p->pResult, k); if (pres->colId == pFuncMsg->colInfo.colId) { - pRuntimeEnv->pCtx[i].param[0].arr = pres->pResult; + pCtx[i].param[0].arr = pres->pResult; break; } } @@ -3872,7 +3302,6 @@ int32_t setParamValue(SQueryRuntimeEnv* pRuntimeEnv) { } } - return 0; } /* @@ -3884,84 +3313,61 @@ int32_t setParamValue(SQueryRuntimeEnv* pRuntimeEnv) { * merged during merge stage. In this case, we need the pTableQueryInfo->lastResRows to decide if there * is a previous result generated or not. */ -void setIntervalQueryRange(SQInfo *pQInfo, TSKEY key) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; - STableQueryInfo *pTableQueryInfo = pQuery->current; - - if (pTableQueryInfo->queryRangeSet) { - pTableQueryInfo->lastKey = key; - } else { - pTableQueryInfo->win.skey = key; - STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey}; +void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) { + SQuery *pQuery = pRuntimeEnv->pQuery; + STableQueryInfo *pTableQueryInfo = pQuery->current; + SResultRowInfo *pWindowResInfo = &pTableQueryInfo->resInfo; - // for too small query range, no data in this interval. - if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey < pQuery->window.skey)) || - (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey < pQuery->window.ekey))) { - return; - } + if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) { + return; + } - /** - * In handling the both ascending and descending order super table query, we need to find the first qualified - * timestamp of this table, and then set the first qualified start timestamp. - * In ascending query, the key is the first qualified timestamp. However, in the descending order query, additional - * operations involve. - */ - STimeWindow w = TSWINDOW_INITIALIZER; - SResultRowInfo *pWindowResInfo = &pTableQueryInfo->resInfo; + pTableQueryInfo->win.skey = key; + STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey}; - TSKEY sk = MIN(win.skey, win.ekey); - TSKEY ek = MAX(win.skey, win.ekey); - getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w); + /** + * In handling the both ascending and descending order super table query, we need to find the first qualified + * timestamp of this table, and then set the first qualified start timestamp. + * In ascending query, the key is the first qualified timestamp. However, in the descending order query, additional + * operations involve. + */ + STimeWindow w = TSWINDOW_INITIALIZER; - if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) { - if (!QUERY_IS_ASC_QUERY(pQuery)) { - assert(win.ekey == pQuery->window.ekey); - } + TSKEY sk = MIN(win.skey, win.ekey); + TSKEY ek = MAX(win.skey, win.ekey); + getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w); - pWindowResInfo->prevSKey = w.skey; + if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) { + if (!QUERY_IS_ASC_QUERY(pQuery)) { + assert(win.ekey == pQuery->window.ekey); } - pTableQueryInfo->queryRangeSet = 1; - pTableQueryInfo->lastKey = pTableQueryInfo->win.skey; + pWindowResInfo->prevSKey = w.skey; } -} -bool requireTimestamp(SQuery *pQuery) { - for (int32_t i = 0; i < pQuery->numOfOutput; i++) { - int32_t functionId = pQuery->pExpr1[i].base.functionId; - if ((aAggs[functionId].status & TSDB_FUNCSTATE_NEED_TS) != 0) { - return true; - } - } - return false; + pTableQueryInfo->lastKey = pTableQueryInfo->win.skey; } -bool needPrimaryTimestampCol(SQuery *pQuery, SDataBlockInfo *pDataBlockInfo) { - /* - * 1. if skey or ekey locates in this block, we need to load the timestamp column to decide the precise position - * 2. if there are top/bottom, first_dst/last_dst functions, we need to load timestamp column in any cases; - */ - STimeWindow *w = &pDataBlockInfo->window; - STableQueryInfo* pTableQueryInfo = pQuery->current; - - bool loadPrimaryTS = (pTableQueryInfo->lastKey >= w->skey && pTableQueryInfo->lastKey <= w->ekey) || - (pQuery->window.ekey >= w->skey && pQuery->window.ekey <= w->ekey) || requireTimestamp(pQuery); - - return loadPrimaryTS; -} +/** + * copyToOutputBuf support copy data in ascending/descending order + * For interval query of both super table and table, copy the data in ascending order, since the output results are + * ordered in SWindowResutl already. While handling the group by query for both table and super table, + * all group result are completed already. + * + * @param pQInfo + * @param result + */ -static int32_t doCopyToSData(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType) { - void* qinfo = GET_QINFO_ADDR(pRuntimeEnv); +static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) { SQuery *pQuery = pRuntimeEnv->pQuery; int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); - int32_t numOfResult = (int32_t) pQuery->rec.rows; // there are already exists result rows + int32_t numOfResult = pBlock->info.rows; // there are already exists result rows int32_t start = 0; int32_t step = -1; - qDebug("QInfo:%p start to copy data from windowResInfo to output buf", qinfo); + qDebug("QInfo:%p start to copy data from windowResInfo to output buf", pRuntimeEnv->qinfo); if (orderType == TSDB_ORDER_ASC) { start = pGroupResInfo->index; step = 1; @@ -3979,56 +3385,56 @@ static int32_t doCopyToSData(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGrou int32_t numOfRowsToCopy = pRow->numOfRows; - //current output space is not enough to accommodate all data of this page, prepare more space - if (numOfRowsToCopy > (pQuery->rec.capacity - numOfResult)) { - int32_t newSize = (int32_t) (pQuery->rec.capacity + (numOfRowsToCopy - numOfResult)); - expandBuffer(pRuntimeEnv, newSize, GET_QINFO_ADDR(pRuntimeEnv)); - } - pGroupResInfo->index += 1; tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pRow->pageId); - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int32_t size = pRuntimeEnv->pCtx[j].outputBytes; - char *out = pQuery->sdata[j]->data + numOfResult * size; - char *in = getPosInResultPage(pRuntimeEnv, j, pRow, page); - memcpy(out, in, size * numOfRowsToCopy); + int16_t offset = 0; + for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) { + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, j); + int32_t bytes = pColInfoData->info.bytes; + + char *out = pColInfoData->pData + numOfResult * bytes; + char *in = getPosInResultPage(pQuery, page, pRow->offset, offset); + memcpy(out, in, bytes * numOfRowsToCopy); + + offset += bytes; } numOfResult += numOfRowsToCopy; - if (numOfResult == pQuery->rec.capacity) { // output buffer is full + if (numOfResult == pRuntimeEnv->resultInfo.capacity) { // output buffer is full break; } } - qDebug("QInfo:%p copy data to query buf completed", qinfo); - return numOfResult; + qDebug("QInfo:%p copy data to query buf completed", pRuntimeEnv->qinfo); + pBlock->info.rows = numOfResult; + return 0; } -/** - * copyToOutputBuf support copy data in ascending/descending order - * For interval query of both super table and table, copy the data in ascending order, since the output results are - * ordered in SWindowResutl already. While handling the group by query for both table and super table, - * all group result are completed already. - * - * @param pQInfo - * @param result - */ -void copyToOutputBuf(SQInfo *pQInfo, SResultRowInfo *pResultInfo) { - SQuery *pQuery = pQInfo->runtimeEnv.pQuery; - SGroupResInfo *pGroupResInfo = &pQInfo->groupResInfo; +static void toSSDataBlock(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock) { + assert(pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup); - assert(pQuery->rec.rows == 0 && pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup); - if (!hasRemainData(pGroupResInfo)) { + pBlock->info.rows = 0; + if (!hasRemainDataInCurrentGroup(pGroupResInfo)) { return; } + SQuery* pQuery = pRuntimeEnv->pQuery; int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC; - pQuery->rec.rows = doCopyToSData(&pQInfo->runtimeEnv, pGroupResInfo, orderType); + doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock); + + SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0); + + if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) { + STimeWindow* w = &pBlock->info.window; + w->skey = *(int64_t*)pInfoData->pData; + w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1)); + } } -static void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv) { +static void updateNumOfRowsInResultRows(SQueryRuntimeEnv *pRuntimeEnv, + SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) { SQuery *pQuery = pRuntimeEnv->pQuery; // update the number of result for each, only update the number of rows for the corresponding window result. @@ -4036,108 +3442,47 @@ static void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv) { return; } - for (int32_t i = 0; i < pRuntimeEnv->resultRowInfo.size; ++i) { - SResultRow *pResult = pRuntimeEnv->resultRowInfo.pResult[i]; + for (int32_t i = 0; i < pResultRowInfo->size; ++i) { + SResultRow *pResult = pResultRowInfo->pResult[i]; - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - int32_t functionId = pRuntimeEnv->pCtx[j].functionId; + for (int32_t j = 0; j < numOfOutput; ++j) { + int32_t functionId = pCtx[j].functionId; if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) { continue; } - SResultRowCellInfo* pCell = getResultCell(pRuntimeEnv, pResult, j); + SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset); pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes)); } } } -static void stableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pDataBlockInfo, SDataStatis *pStatis, - SArray *pDataBlock, __block_search_fn_t searchFn) { - SQuery * pQuery = pRuntimeEnv->pQuery; - STableQueryInfo* pTableQueryInfo = pQuery->current; +static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) { + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; + SQuery *pQuery = pRuntimeEnv->pQuery; - SResultRowInfo * pResultRowInfo = &pTableQueryInfo->resInfo; - pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0 : pDataBlockInfo->rows - 1; + SSDataBlock* pRes = pRuntimeEnv->outputBuf; - if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->groupbyColumn) { - rowwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, pDataBlock); + if (pQuery->pExpr2 == NULL) { + for (int32_t col = 0; col < pQuery->numOfOutput; ++col) { + SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col); + memmove(data, pColRes->pData, pColRes->info.bytes * pRes->info.rows); + data += pColRes->info.bytes * pRes->info.rows; + } } else { - blockwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, searchFn, pDataBlock); + for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) { + SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col); + memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows); + data += pColRes->info.bytes * numOfRows; + } } - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - updateResultRowIndex(pResultRowInfo, pTableQueryInfo, QUERY_IS_ASC_QUERY(pQuery), pRuntimeEnv->timeWindowInterpo); - } -} - -bool hasNotReturnedResults(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo) { - SQuery *pQuery = pRuntimeEnv->pQuery; - SFillInfo *pFillInfo = pRuntimeEnv->pFillInfo; - - if (!Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - return false; - } - - if (pQuery->limit.limit > 0 && pQuery->rec.total >= pQuery->limit.limit) { - return false; - } - - if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) { - // There are results not returned to client yet, so filling applied to the remain result is required firstly. - if (taosFillHasMoreResults(pFillInfo)) { - return true; - } - - /* - * While the code reaches here, there are no results remains now. - * If query is not completed yet, the gaps between two results blocks need to be handled after next data block - * is retrieved from TSDB. - * - * NOTE: If the result set is not the first block, the gap in front of the result set will be filled. If the result - * set is the FIRST result block, the gap between the start time of query time window and the timestamp of the - * first result row in the actual result set will fill nothing. - */ - int32_t numOfTotal = (int32_t)getNumOfResultsAfterFillGap(pFillInfo, pQuery->window.ekey, (int32_t)pQuery->rec.capacity); - return numOfTotal > 0; - } else { // there are results waiting for returned to client. - if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED) && hasRemainData(pGroupResInfo) && - (pRuntimeEnv->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery))) { - return true; - } - } - - return false; -} - -static int16_t getNumOfFinalResCol(SQuery* pQuery) { - return pQuery->pExpr2 == NULL? pQuery->numOfOutput:pQuery->numOfExpr2; -} - -static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) { - SQuery *pQuery = pQInfo->runtimeEnv.pQuery; - - if (pQuery->pExpr2 == NULL) { - for (int32_t col = 0; col < pQuery->numOfOutput; ++col) { - int32_t bytes = pQuery->pExpr1[col].bytes; - - memmove(data, pQuery->sdata[col]->data, bytes * numOfRows); - data += bytes * numOfRows; - } - } else { - for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) { - int32_t bytes = pQuery->pExpr2[col].bytes; - - memmove(data, pQuery->sdata[col]->data, bytes * numOfRows); - data += bytes * numOfRows; - } - } - - int32_t numOfTables = (int32_t) taosHashGetSize(pQInfo->arrTableIdInfo); + int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap); *(int32_t*)data = htonl(numOfTables); data += sizeof(int32_t); int32_t total = 0; - STableIdInfo* item = taosHashIterate(pQInfo->arrTableIdInfo, NULL); + STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL); while(item) { STableIdInfo* pDst = (STableIdInfo*)data; @@ -4149,75 +3494,34 @@ static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data total++; qDebug("QInfo:%p set subscribe info, tid:%d, uid:%"PRIu64", skey:%"PRId64, pQInfo, item->tid, item->uid, item->key); - item = taosHashIterate(pQInfo->arrTableIdInfo, item); + item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, item); } qDebug("QInfo:%p set %d subscribe info", pQInfo, total); - // Check if query is completed or not for stable query or normal table query respectively. - if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - if (pQInfo->runtimeEnv.stableQuery) { - if (IS_STASBLE_QUERY_OVER(pQInfo)) { - setQueryStatus(pQuery, QUERY_OVER); - } - } else { - if (!hasNotReturnedResults(&pQInfo->runtimeEnv, &pQInfo->groupResInfo)) { - setQueryStatus(pQuery, QUERY_OVER); - } - } + if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) { + setQueryStatus(pRuntimeEnv, QUERY_OVER); } } -int32_t doFillGapsInResults(SQueryRuntimeEnv* pRuntimeEnv, tFilePage **pDst) { - SQInfo *pQInfo = GET_QINFO_ADDR(pRuntimeEnv); - SQuery *pQuery = pRuntimeEnv->pQuery; - SFillInfo* pFillInfo = pRuntimeEnv->pFillInfo; - - while (1) { - int32_t ret = (int32_t)taosFillResultDataBlock(pFillInfo, (tFilePage**)pQuery->sdata, (int32_t)pQuery->rec.capacity); - - // todo apply limit output function - /* reached the start position of according to offset value, return immediately */ - if (pQuery->limit.offset == 0) { - qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows", pQInfo, pFillInfo->numOfRows, ret); - return ret; - } - - if (pQuery->limit.offset < ret) { - qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows, offset:%" PRId64 ". Discard due to offset, remain:%" PRId64 ", new offset:%d", - pQInfo, pFillInfo->numOfRows, ret, pQuery->limit.offset, ret - pQuery->limit.offset, 0); - - ret -= (int32_t)pQuery->limit.offset; - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { //???pExpr1 or pExpr2 - memmove(pDst[i]->data, pDst[i]->data + pQuery->pExpr1[i].bytes * pQuery->limit.offset, - ret * pQuery->pExpr1[i].bytes); - } - - pQuery->limit.offset = 0; - return ret; - } else { - qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows, offset:%" PRId64 ". Discard due to offset, " - "remain:%d, new offset:%" PRId64, pQInfo, pFillInfo->numOfRows, ret, pQuery->limit.offset, 0, - pQuery->limit.offset - ret); - - pQuery->limit.offset -= ret; - ret = 0; - } - - // no data in current data after fill - int32_t numOfTotal = (int32_t)getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, (int32_t)pQuery->rec.capacity); - if (numOfTotal == 0) { - return 0; - } +int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) { + void** p = calloc(pFillInfo->numOfCols, POINTER_BYTES); + for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) { + SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i); + p[i] = pColInfoData->pData; } + + pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity); + tfree(p); + return pOutput->info.rows; } void queryCostStatis(SQInfo *pQInfo) { SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQueryCostInfo *pSummary = &pRuntimeEnv->summary; + SQueryCostInfo *pSummary = &pQInfo->summary; uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable); - hashSize += taosHashGetMemSize(pQInfo->tableqinfoGroupInfo.map); + hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map); pSummary->hashSize = hashSize; // add the merge time @@ -4241,293 +3545,241 @@ void queryCostStatis(SQInfo *pQInfo) { pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0); } -static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) { - SQuery *pQuery = pRuntimeEnv->pQuery; - STableQueryInfo* pTableQueryInfo = pQuery->current; - - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - - if (pQuery->limit.offset == pBlockInfo->rows) { // current block will ignore completed - pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->window.ekey + step : pBlockInfo->window.skey + step; - pQuery->limit.offset = 0; - return; - } - - if (QUERY_IS_ASC_QUERY(pQuery)) { - pQuery->pos = (int32_t)pQuery->limit.offset; - } else { - pQuery->pos = pBlockInfo->rows - (int32_t)pQuery->limit.offset - 1; - } - - assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->rows - 1); - - SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); - SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); - - // update the pQuery->limit.offset value, and pQuery->pos value - TSKEY *keys = (TSKEY *) pColInfoData->pData; - - // update the offset value - pTableQueryInfo->lastKey = keys[pQuery->pos]; - pQuery->limit.offset = 0; - - int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock); - - qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QINFO_ADDR(pRuntimeEnv), - pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey); -} -static void freeTableBlockDist(STableBlockDist *pTableBlockDist) { - if (pTableBlockDist != NULL) { - taosArrayDestroy(pTableBlockDist->dataBlockInfos); - free(pTableBlockDist->result); - free(pTableBlockDist); - } -} -static int32_t getPercentileFromSortedArray(const SArray* pArray, double rate) { - int32_t len = (int32_t)taosArrayGetSize(pArray); - if (len <= 0) { - return 0; - } - assert(rate >= 0 && rate <= 1.0); - int idx = (int32_t)((len - 1) * rate); - return ((SDataBlockInfo *)(taosArrayGet(pArray, idx)))->rows; -} -static int compareBlockInfo(const void *pLeft, const void *pRight) { - int32_t left = ((SDataBlockInfo *)pLeft)->rows; - int32_t right = ((SDataBlockInfo *)pRight)->rows; - if (left > right) return 1; - if (left < right) return -1; - return 0; -} - -static void generateBlockDistResult(STableBlockDist *pTableBlockDist) { - if (pTableBlockDist == NULL) { - return; - } - int64_t min = 0, max = 0, avg = 0; - SArray* blockInfos= pTableBlockDist->dataBlockInfos; - int64_t totalRows = 0, totalBlocks = taosArrayGetSize(blockInfos); - for (size_t i = 0; i < taosArrayGetSize(blockInfos); i++) { - SDataBlockInfo *blockInfo = taosArrayGet(blockInfos, i); - int64_t rows = blockInfo->rows; - min = MIN(min, rows); - max = MAX(max, rows); - totalRows += rows; - } - avg = totalBlocks > 0 ? (int64_t)(totalRows/totalBlocks) : 0; - - taosArraySort(blockInfos, compareBlockInfo); - - int sz = sprintf(pTableBlockDist->result, - "summery: \n\t 5th=[%d], 25th=[%d], 50th=[%d],75th=[%d], 95th=[%d], 99th=[%d] \n\t min=[%"PRId64"], max=[%"PRId64"], avg = [%"PRId64"] \n\t totalRows=[%"PRId64"], totalBlocks=[%"PRId64"] \n\t seekHeaderTimeCost=[%"PRId64"(us)] \n\t rowsInMem=[%"PRId64"]", - getPercentileFromSortedArray(blockInfos, 0.05), getPercentileFromSortedArray(blockInfos, 0.25), getPercentileFromSortedArray(blockInfos, 0.50), - getPercentileFromSortedArray(blockInfos, 0.75), getPercentileFromSortedArray(blockInfos, 0.95), getPercentileFromSortedArray(blockInfos, 0.99), - min, max, avg, - totalRows, totalBlocks, - pTableBlockDist->firstSeekTimeUs, - pTableBlockDist->numOfRowsInMemTable); - UNUSED(sz); - return; -} -void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0) { - return; - } - - pQuery->pos = 0; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - - STableQueryInfo* pTableQueryInfo = pQuery->current; - TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle; - - SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; - while (tsdbNextDataBlock(pQueryHandle)) { - if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) { - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } - - tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo); - - if (pQuery->limit.offset > blockInfo.rows) { - pQuery->limit.offset -= blockInfo.rows; - pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.window.ekey : blockInfo.window.skey; - pTableQueryInfo->lastKey += step; - - qDebug("QInfo:%p skip rows:%d, offset:%" PRId64, GET_QINFO_ADDR(pRuntimeEnv), blockInfo.rows, - pQuery->limit.offset); - } else { // find the appropriated start position in current block - updateOffsetVal(pRuntimeEnv, &blockInfo); - break; - } - } - - if (terrno != TSDB_CODE_SUCCESS) { - longjmp(pRuntimeEnv->env, terrno); - } -} - -static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) { - SQuery *pQuery = pRuntimeEnv->pQuery; - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - - assert(pQuery->limit.offset == 0); - STimeWindow tw = *win; - getNextTimeWindow(pQuery, &tw); - - if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || - (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) { - - // load the data block and check data remaining in current data block - // TODO optimize performance - SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); - SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); - - tw = *win; - int32_t startPos = - getNextQualifiedWindow(pRuntimeEnv, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1); - assert(startPos >= 0); - - // set the abort info - pQuery->pos = startPos; - - // reset the query start timestamp - pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos]; - pQuery->window.skey = pTableQueryInfo->win.skey; - TSKEY key = pTableQueryInfo->win.skey; - - pWindowResInfo->prevSKey = tw.skey; - int32_t index = pRuntimeEnv->resultRowInfo.curIndex; - - int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock); - pRuntimeEnv->resultRowInfo.curIndex = index; // restore the window index - - qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64, - GET_QINFO_ADDR(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, - pQuery->current->lastKey); - - return key; - } else { // do nothing - pQuery->window.skey = tw.skey; - pWindowResInfo->prevSKey = tw.skey; - pTableQueryInfo->lastKey = tw.skey; - - return tw.skey; - } - - return true; -} - -static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { - SQuery *pQuery = pRuntimeEnv->pQuery; - if (QUERY_IS_ASC_QUERY(pQuery)) { - assert(*start <= pQuery->current->lastKey); - } else { - assert(*start >= pQuery->current->lastKey); - } - - // if queried with value filter, do NOT forward query start position - if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) { - return true; - } - - /* - * 1. for interval without interpolation query we forward pQuery->interval.interval at a time for - * pQuery->limit.offset times. Since hole exists, pQuery->interval.interval*pQuery->limit.offset value is - * not valid. otherwise, we only forward pQuery->limit.offset number of points - */ - assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL); - - STimeWindow w = TSWINDOW_INITIALIZER; - bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); - - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - STableQueryInfo *pTableQueryInfo = pQuery->current; - - SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; - while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) { - tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo); - - if (QUERY_IS_ASC_QUERY(pQuery)) { - if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) { - getAlignQueryTimeWindow(pQuery, blockInfo.window.skey, blockInfo.window.skey, pQuery->window.ekey, &w); - pWindowResInfo->prevSKey = w.skey; - } - } else { - getAlignQueryTimeWindow(pQuery, blockInfo.window.ekey, pQuery->window.ekey, blockInfo.window.ekey, &w); - pWindowResInfo->prevSKey = w.skey; - } - - // the first time window - STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQuery); - - while (pQuery->limit.offset > 0) { - STimeWindow tw = win; - - if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) { - pQuery->limit.offset -= 1; - pWindowResInfo->prevSKey = win.skey; - - // current time window is aligned with blockInfo.window.ekey - // restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL; - if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) { - pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL; - } - } - - if (pQuery->limit.offset == 0) { - *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); - return true; - } - - // current window does not ended in current data block, try next data block - getNextTimeWindow(pQuery, &tw); - - /* - * If the next time window still starts from current data block, - * load the primary timestamp column first, and then find the start position for the next queried time window. - * Note that only the primary timestamp column is required. - * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required - * time window resides in current data block. - */ - if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) { - - SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); - SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); - - if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) { - pQuery->limit.offset -= 1; - } - - if (pQuery->limit.offset == 0) { - *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); - return true; - } else { - tw = win; - int32_t startPos = - getNextQualifiedWindow(pRuntimeEnv, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1); - assert(startPos >= 0); - - // set the abort info - pQuery->pos = startPos; - pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos]; - pWindowResInfo->prevSKey = tw.skey; - win = tw; - } - } else { - break; // offset is not 0, and next time window begins or ends in the next block. - } - } - } - - // check for error - if (terrno != TSDB_CODE_SUCCESS) { - longjmp(pRuntimeEnv->env, terrno); - } - - return true; -} +//static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) { +// SQuery *pQuery = pRuntimeEnv->pQuery; +// STableQueryInfo* pTableQueryInfo = pQuery->current; +// +// int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); +// +// if (pQuery->limit.offset == pBlockInfo->rows) { // current block will ignore completed +// pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->window.ekey + step : pBlockInfo->window.skey + step; +// pQuery->limit.offset = 0; +// return; +// } +// +// if (QUERY_IS_ASC_QUERY(pQuery)) { +// pQuery->pos = (int32_t)pQuery->limit.offset; +// } else { +// pQuery->pos = pBlockInfo->rows - (int32_t)pQuery->limit.offset - 1; +// } +// +// assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->rows - 1); +// +// SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); +// SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); +// +// // update the pQuery->limit.offset value, and pQuery->pos value +// TSKEY *keys = (TSKEY *) pColInfoData->pData; +// +// // update the offset value +// pTableQueryInfo->lastKey = keys[pQuery->pos]; +// pQuery->limit.offset = 0; +// +// int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock); +// +// qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, pRuntimeEnv->qinfo, +// pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey); +//} + +//void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) { +// SQuery *pQuery = pRuntimeEnv->pQuery; +// +// if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0) { +// return; +// } +// +// pQuery->pos = 0; +// int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); +// +// STableQueryInfo* pTableQueryInfo = pQuery->current; +// TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle; +// +// SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; +// while (tsdbNextDataBlock(pQueryHandle)) { +// if (isQueryKilled(pRuntimeEnv->qinfo)) { +// longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); +// } +// +// tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo); +// +// if (pQuery->limit.offset > blockInfo.rows) { +// pQuery->limit.offset -= blockInfo.rows; +// pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.window.ekey : blockInfo.window.skey; +// pTableQueryInfo->lastKey += step; +// +// qDebug("QInfo:%p skip rows:%d, offset:%" PRId64, pRuntimeEnv->qinfo, blockInfo.rows, +// pQuery->limit.offset); +// } else { // find the appropriated start position in current block +// updateOffsetVal(pRuntimeEnv, &blockInfo); +// break; +// } +// } +// +// if (terrno != TSDB_CODE_SUCCESS) { +// longjmp(pRuntimeEnv->env, terrno); +// } +//} + +//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) { +// SQuery *pQuery = pRuntimeEnv->pQuery; +// SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; +// +// assert(pQuery->limit.offset == 0); +// STimeWindow tw = *win; +// getNextTimeWindow(pQuery, &tw); +// +// if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || +// (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) { +// +// // load the data block and check data remaining in current data block +// // TODO optimize performance +// SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); +// SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); +// +// tw = *win; +// int32_t startPos = +// getNextQualifiedWindow(pQuery, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1); +// assert(startPos >= 0); +// +// // set the abort info +// pQuery->pos = startPos; +// +// // reset the query start timestamp +// pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos]; +// pQuery->window.skey = pTableQueryInfo->win.skey; +// TSKEY key = pTableQueryInfo->win.skey; +// +// pWindowResInfo->prevSKey = tw.skey; +// int32_t index = pRuntimeEnv->resultRowInfo.curIndex; +// +// int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock); +// pRuntimeEnv->resultRowInfo.curIndex = index; // restore the window index +// +// qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64, +// pRuntimeEnv->qinfo, pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, +// pQuery->current->lastKey); +// +// return key; +// } else { // do nothing +// pQuery->window.skey = tw.skey; +// pWindowResInfo->prevSKey = tw.skey; +// pTableQueryInfo->lastKey = tw.skey; +// +// return tw.skey; +// } +// +// return true; +//} + +//static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { +// SQuery *pQuery = pRuntimeEnv->pQuery; +// if (QUERY_IS_ASC_QUERY(pQuery)) { +// assert(*start <= pQuery->current->lastKey); +// } else { +// assert(*start >= pQuery->current->lastKey); +// } +// +// // if queried with value filter, do NOT forward query start position +// if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) { +// return true; +// } +// +// /* +// * 1. for interval without interpolation query we forward pQuery->interval.interval at a time for +// * pQuery->limit.offset times. Since hole exists, pQuery->interval.interval*pQuery->limit.offset value is +// * not valid. otherwise, we only forward pQuery->limit.offset number of points +// */ +// assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL); +// +// STimeWindow w = TSWINDOW_INITIALIZER; +// bool ascQuery = QUERY_IS_ASC_QUERY(pQuery); +// +// SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; +// STableQueryInfo *pTableQueryInfo = pQuery->current; +// +// SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; +// while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) { +// tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo); +// +// if (QUERY_IS_ASC_QUERY(pQuery)) { +// if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) { +// getAlignQueryTimeWindow(pQuery, blockInfo.window.skey, blockInfo.window.skey, pQuery->window.ekey, &w); +// pWindowResInfo->prevSKey = w.skey; +// } +// } else { +// getAlignQueryTimeWindow(pQuery, blockInfo.window.ekey, pQuery->window.ekey, blockInfo.window.ekey, &w); +// pWindowResInfo->prevSKey = w.skey; +// } +// +// // the first time window +// STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQuery); +// +// while (pQuery->limit.offset > 0) { +// STimeWindow tw = win; +// +// if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) { +// pQuery->limit.offset -= 1; +// pWindowResInfo->prevSKey = win.skey; +// +// // current time window is aligned with blockInfo.window.ekey +// // restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL; +// if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) { +// pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL; +// } +// } +// +// if (pQuery->limit.offset == 0) { +// *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); +// return true; +// } +// +// // current window does not ended in current data block, try next data block +// getNextTimeWindow(pQuery, &tw); +// +// /* +// * If the next time window still starts from current data block, +// * load the primary timestamp column first, and then find the start position for the next queried time window. +// * Note that only the primary timestamp column is required. +// * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required +// * time window resides in current data block. +// */ +// if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) { +// +// SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); +// SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); +// +// if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) { +// pQuery->limit.offset -= 1; +// } +// +// if (pQuery->limit.offset == 0) { +// *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); +// return true; +// } else { +// tw = win; +// int32_t startPos = +// getNextQualifiedWindow(pQuery, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1); +// assert(startPos >= 0); +// +// // set the abort info +// pQuery->pos = startPos; +// pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos]; +// pWindowResInfo->prevSKey = tw.skey; +// win = tw; +// } +// } else { +// break; // offset is not 0, and next time window begins or ends in the next block. +// } +// } +// } +// +// // check for error +// if (terrno != TSDB_CODE_SUCCESS) { +// longjmp(pRuntimeEnv->env, terrno); +// } +// +// return true; +//} static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo); @@ -4535,40 +3787,40 @@ static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; + // TODO set the tags scan handle if (onlyQueryTags(pQuery)) { return TSDB_CODE_SUCCESS; } - if (isSTableQuery && (!QUERY_IS_INTERVAL_QUERY(pQuery)) && (!isFixedOutputQuery(pRuntimeEnv))) { - return TSDB_CODE_SUCCESS; - } - STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); + if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) { + cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER; + } if (!isSTableQuery - && (pQInfo->tableqinfoGroupInfo.numOfTables == 1) + && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1) && (cond.order == TSDB_ORDER_ASC) && (!QUERY_IS_INTERVAL_QUERY(pQuery)) && (!isGroupbyColumn(pQuery->pGroupbyExpr)) - && (!isFixedOutputQuery(pRuntimeEnv)) + && (!isFixedOutputQuery(pQuery)) ) { - SArray* pa = GET_TABLEGROUP(pQInfo, 0); + SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0); STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0); cond.twindow = pCheckInfo->win; } terrno = TSDB_CODE_SUCCESS; if (isFirstLastRowQuery(pQuery)) { - pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); + pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef); // update the query time window pQuery->window = cond.twindow; - if (pQInfo->tableGroupInfo.numOfTables == 0) { - pQInfo->tableqinfoGroupInfo.numOfTables = 0; + if (pQuery->tableGroupInfo.numOfTables == 0) { + pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0; } else { - size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv); for(int32_t i = 0; i < numOfGroups; ++i) { - SArray *group = GET_TABLEGROUP(pQInfo, i); + SArray *group = GET_TABLEGROUP(pRuntimeEnv, i); size_t t = taosArrayGetSize(group); for (int32_t j = 0; j < t; ++j) { @@ -4580,26 +3832,24 @@ static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) } } } else if (isPointInterpoQuery(pQuery)) { - pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); + pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef); } else { - pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); + pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef); } return terrno; } -static SFillColInfo* createFillColInfo(SQuery* pQuery) { - int32_t numOfCols = getNumOfFinalResCol(pQuery); +static SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, int64_t* fillVal) { int32_t offset = 0; - SFillColInfo* pFillCol = calloc(numOfCols, sizeof(SFillColInfo)); + SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo)); if (pFillCol == NULL) { return NULL; } - // TODO refactor - for(int32_t i = 0; i < numOfCols; ++i) { - SExprInfo* pExprInfo = (pQuery->pExpr2 == NULL)? &pQuery->pExpr1[i]:&pQuery->pExpr2[i]; + for(int32_t i = 0; i < numOfOutput; ++i) { + SExprInfo* pExprInfo = &pExpr[i]; pFillCol[i].col.bytes = pExprInfo->bytes; pFillCol[i].col.type = (int8_t)pExprInfo->type; @@ -4607,7 +3857,7 @@ static SFillColInfo* createFillColInfo(SQuery* pQuery) { pFillCol[i].tagIndex = -2; pFillCol[i].flag = TSDB_COL_NORMAL; // always be ta normal column for table query pFillCol[i].functionId = pExprInfo->base.functionId; - pFillCol[i].fillVal.i = pQuery->fillVal[i]; + pFillCol[i].fillVal.i = fillVal[i]; offset += pExprInfo->bytes; } @@ -4619,11 +3869,15 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *ts SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; + pQuery->tsdb = tsdb; + + pQuery->topBotQuery = isTopBottomQuery(pQuery); + pQuery->hasTagResults = hasTagValOutput(pQuery); + pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery); + pQuery->stabledev = isStabledev(pQuery); - pRuntimeEnv->topBotQuery = isTopBottomQuery(pQuery); - pRuntimeEnv->hasTagResults = hasTagValOutput(pQuery); - pRuntimeEnv->timeWindowInterpo = timeWindowInterpoRequired(pQuery); pRuntimeEnv->prevResult = prevResult; + pRuntimeEnv->qinfo = pQInfo; setScanLimitationByResultBuffer(pQuery); @@ -4632,17 +3886,31 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *ts return code; } - pQInfo->tsdb = tsdb; - pQInfo->vgId = vgId; - pQInfo->groupResInfo.totalGroup = (int32_t) (isSTableQuery? GET_NUM_OF_TABLEGROUP(pQInfo):0); + pQuery->tsdb = tsdb; + pQuery->vgId = vgId; + pQuery->stableQuery = isSTableQuery; + pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr); + pQuery->interBufSize = getOutputInterResultBufSize(pQuery); + + pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0); pRuntimeEnv->pQuery = pQuery; pRuntimeEnv->pTsBuf = pTsBuf; pRuntimeEnv->cur.vgroupIndex = -1; - pRuntimeEnv->stableQuery = isSTableQuery; - pRuntimeEnv->prevGroupId = INT32_MIN; - pRuntimeEnv->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr); - pRuntimeEnv->stabledev = isStabledev(pQuery); + setResultBufSize(pQuery, &pRuntimeEnv->resultInfo); + + if (onlyQueryTags(pQuery)) { + pRuntimeEnv->resultInfo.capacity = 4096; + pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQuery->pExpr1, pQuery->numOfOutput); + } else if (pQuery->queryBlockDist) { + pRuntimeEnv->pTableScanner = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv); + } else if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) { + pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv); + } else if (needReverseScan(pQuery)) { + pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1); + } else { + pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery)); + } if (pTsBuf != NULL) { int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC; @@ -4650,109 +3918,26 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *ts } int32_t ps = DEFAULT_PAGE_SIZE; - int32_t rowsize = 0; - getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); - int32_t TENMB = 1024*1024*10; - - if (isSTableQuery && !onlyQueryTags(pRuntimeEnv->pQuery)) { - code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TENMB, pQInfo); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - if (!QUERY_IS_INTERVAL_QUERY(pQuery)) { - int16_t type = TSDB_DATA_TYPE_NULL; - if (pRuntimeEnv->groupbyColumn) { // group by columns not tags; - type = getGroupbyColumnType(pQuery, pQuery->pGroupbyExpr); - } else { - type = TSDB_DATA_TYPE_INT; // group id - } - - code = initResultRowInfo(&pRuntimeEnv->resultRowInfo, 8, type); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - } else if (pRuntimeEnv->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery) || (!isSTableQuery)) { - int32_t numOfResultRows = getInitialPageNum(pQInfo); - getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); - code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TENMB, pQInfo); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - int16_t type = TSDB_DATA_TYPE_NULL; - if (pRuntimeEnv->groupbyColumn) { - type = getGroupbyColumnType(pQuery, pQuery->pGroupbyExpr); - } else { - type = TSDB_DATA_TYPE_TIMESTAMP; - } + getIntermediateBufInfo(pRuntimeEnv, &ps, &pQuery->intermediateResultRowSize); - code = initResultRowInfo(&pRuntimeEnv->resultRowInfo, numOfResultRows, type); - if (code != TSDB_CODE_SUCCESS) { - return code; - } + int32_t TENMB = 1024*1024*10; + code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo); + if (code != TSDB_CODE_SUCCESS) { + return code; } // create runtime environment - code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQInfo->tableGroupInfo.numOfTables, pQuery->order.order, pQInfo->vgId); + int32_t numOfTables = (int32_t)pQuery->tableGroupInfo.numOfTables; + pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo)); + code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables); if (code != TSDB_CODE_SUCCESS) { return code; } - if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) { - SFillColInfo* pColInfo = createFillColInfo(pQuery); - STimeWindow w = TSWINDOW_INITIALIZER; - - TSKEY sk = MIN(pQuery->window.skey, pQuery->window.ekey); - TSKEY ek = MAX(pQuery->window.skey, pQuery->window.ekey); - getAlignQueryTimeWindow(pQuery, pQuery->window.skey, sk, ek, &w); - - int32_t numOfCols = getNumOfFinalResCol(pQuery); - pRuntimeEnv->pFillInfo = taosCreateFillInfo(pQuery->order.order, w.skey, 0, (int32_t)pQuery->rec.capacity, numOfCols, - pQuery->interval.sliding, pQuery->interval.slidingUnit, (int8_t)pQuery->precision, - pQuery->fillType, pColInfo, pQInfo); - } - - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); + setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED); return TSDB_CODE_SUCCESS; } -static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) { - SQuery *pQuery = pRuntimeEnv->pQuery; - - for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { - SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[i]); - if (pResInfo != NULL) { - pResInfo->complete = false; - } - } -} - -static FORCE_INLINE void setEnvForEachBlock(SQInfo* pQInfo, STableQueryInfo* pTableQueryInfo, SDataBlockInfo* pBlockInfo) { - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery* pQuery = pQInfo->runtimeEnv.pQuery; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - - if (pRuntimeEnv->hasTagResults || pRuntimeEnv->pTsBuf != NULL) { - setTagVal(pRuntimeEnv, pTableQueryInfo->pTable); - } - - if (pRuntimeEnv->pTsBuf != NULL) { - setTimestampListJoinInfo(pQInfo, pTableQueryInfo); - } - - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - if (!QUERY_IS_ASC_QUERY(pRuntimeEnv->pQuery)) { - setIntervalQueryRange(pQInfo, pBlockInfo->window.ekey); - } else { - setIntervalQueryRange(pQInfo, pBlockInfo->window.skey); - } - } else { // non-interval query - setExecutionContext(pQInfo, pTableQueryInfo->groupIndex, pBlockInfo->window.ekey + step); - } -} - static void doTableQueryInfoTimeWindowCheck(SQuery* pQuery, STableQueryInfo* pTableQueryInfo) { if (QUERY_IS_ASC_QUERY(pQuery)) { assert( @@ -4767,1123 +3952,1210 @@ static void doTableQueryInfoTimeWindowCheck(SQuery* pQuery, STableQueryInfo* pTa } } -static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery* pQuery = pRuntimeEnv->pQuery; - SQueryCostInfo* summary = &pRuntimeEnv->summary; +STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) { + STsdbQueryCond cond = { + .colList = pQuery->colList, + .order = pQuery->order.order, + .numOfCols = pQuery->numOfCols, + .type = BLOCK_LOAD_OFFSET_SEQ_ORDER, + .loadExternalRows = false, + }; - int64_t st = taosGetTimestampMs(); + TIME_WINDOW_COPY(cond.twindow, *win); + return cond; +} - TsdbQueryHandleT pQueryHandle = IS_MASTER_SCAN(pRuntimeEnv)? pRuntimeEnv->pQueryHandle : pRuntimeEnv->pSecQueryHandle; - SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; +static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) { + STableIdInfo tidInfo; + STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable); - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); + tidInfo.uid = id->uid; + tidInfo.tid = id->tid; + tidInfo.key = pTableQueryInfo->lastKey; - while (tsdbNextDataBlock(pQueryHandle)) { - summary->totalBlocks += 1; + return tidInfo; +} - if (isQueryKilled(pQInfo)) { - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } +static void updateTableIdInfo(STableQueryInfo* pTableQueryInfo, SSDataBlock* pBlock, SHashObj* pTableIdInfo, int32_t order) { + int32_t step = GET_FORWARD_DIRECTION_FACTOR(order); + pTableQueryInfo->lastKey = ((order == TSDB_ORDER_ASC)? pBlock->info.window.ekey:pBlock->info.window.skey) + step; - tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo); - STableQueryInfo **pTableQueryInfo = (STableQueryInfo**) taosHashGet(pQInfo->tableqinfoGroupInfo.map, &blockInfo.tid, sizeof(blockInfo.tid)); - if(pTableQueryInfo == NULL) { - break; - } + STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo); + STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid)); + if (idinfo != NULL) { + assert(idinfo->tid == tidInfo.tid && idinfo->uid == tidInfo.uid); + idinfo->key = tidInfo.key; + } else { + taosHashPut(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo)); + } +} - pQuery->current = *pTableQueryInfo; - doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo); +static void doCloseAllTimeWindow(SQueryRuntimeEnv* pRuntimeEnv) { + size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv); + for (int32_t i = 0; i < numOfGroup; ++i) { + SArray* group = GET_TABLEGROUP(pRuntimeEnv, i); - if (!pRuntimeEnv->groupbyColumn) { - setEnvForEachBlock(pQInfo, *pTableQueryInfo, &blockInfo); + size_t num = taosArrayGetSize(group); + for (int32_t j = 0; j < num; ++j) { + STableQueryInfo* item = taosArrayGetP(group, j); + closeAllResultRows(&item->resInfo); } + } +} - if (pRuntimeEnv->stabledev) { - for(int32_t i = 0; i < pQuery->numOfOutput; ++i) { - if (pQuery->pExpr1[i].base.functionId == TSDB_FUNC_STDDEV_DST) { - setParamValue(pRuntimeEnv); - break; - } - } - } +static SSDataBlock* doTableScanImpl(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; - uint32_t status = 0; - SDataStatis *pStatis = NULL; - SArray *pDataBlock = NULL; + STableScanInfo* pTableScanInfo = pOperator->info; + SSDataBlock* pBlock = &pTableScanInfo->block; + SQuery* pQuery = pOperator->pRuntimeEnv->pQuery; + STableGroupInfo* pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo; - int32_t ret = loadDataBlockOnDemand(pRuntimeEnv, &pQuery->current->resInfo, pQueryHandle, &blockInfo, &pStatis, &pDataBlock, &status); - if (ret != TSDB_CODE_SUCCESS) { - break; + while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) { + if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) { + longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); } - if (status == BLK_DATA_DISCARD) { - pQuery->current->lastKey = QUERY_IS_ASC_QUERY(pQuery)? blockInfo.window.ekey + step : blockInfo.window.skey + step; - continue; + pTableScanInfo->numOfBlocks += 1; + tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info); + + // todo opt + if (pTableGroupInfo->numOfTables > 1 || (pQuery->current == NULL && pTableGroupInfo->numOfTables == 1)) { + STableQueryInfo** pTableQueryInfo = + (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid)); + if (pTableQueryInfo == NULL) { + break; + } + + pQuery->current = *pTableQueryInfo; + doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo); } - summary->totalRows += blockInfo.rows; - stableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, pDataBlock, binarySearchForKey); + // this function never returns error? + uint32_t status; + int32_t code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status); + if (code != TSDB_CODE_SUCCESS) { + longjmp(pOperator->pRuntimeEnv->env, code); + } - qDebug("QInfo:%p check data block completed, uid:%"PRId64", tid:%d, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, " - "lastKey:%" PRId64, - pQInfo, blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, - pQuery->current->lastKey); - } + // current block is ignored according to filter result by block statistics data, continue load the next block + if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) { + continue; + } - if (terrno != TSDB_CODE_SUCCESS) { - longjmp(pRuntimeEnv->env, terrno); + return pBlock; } - updateWindowResNumOfRes(pRuntimeEnv); - - int64_t et = taosGetTimestampMs(); - return et - st; + return NULL; } -static bool multiTableMultioutputHelper(SQInfo *pQInfo, int32_t index) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; +static SSDataBlock* doTableScan(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); - SArray *group = GET_TABLEGROUP(pQInfo, 0); - STableQueryInfo* pCheckInfo = taosArrayGetP(group, index); + STableScanInfo *pTableScanInfo = pOperator->info; + SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv; + SQuery* pQuery = pRuntimeEnv->pQuery; - if (pRuntimeEnv->hasTagResults || pRuntimeEnv->pTsBuf != NULL) { - setTagVal(pRuntimeEnv, pCheckInfo->pTable); - } + SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo; - STableId* id = TSDB_TABLEID(pCheckInfo->pTable); - qDebug("QInfo:%p query on (%d): uid:%" PRIu64 ", tid:%d, qrange:%" PRId64 "-%" PRId64, pQInfo, index, - id->uid, id->tid, pCheckInfo->lastKey, pCheckInfo->win.ekey); + while (pTableScanInfo->current < pTableScanInfo->times) { + SSDataBlock* p = doTableScanImpl(pOperator); + if (p != NULL) { + return p; + } - STsdbQueryCond cond = { - .twindow = {pCheckInfo->lastKey, pCheckInfo->win.ekey}, - .order = pQuery->order.order, - .colList = pQuery->colList, - .numOfCols = pQuery->numOfCols, - .loadExternalRows = false, - }; + if (++pTableScanInfo->current >= pTableScanInfo->times) { + if (pTableScanInfo->reverseTimes <= 0) { + return NULL; + } else { + break; + } + } - // todo refactor - SArray *g1 = taosArrayInit(1, POINTER_BYTES); - SArray *tx = taosArrayInit(1, sizeof(STableKeyInfo)); + // do prepare for the next round table scan operation + STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); + tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond); - STableKeyInfo info = {.pTable = pCheckInfo->pTable, .lastKey = pCheckInfo->lastKey}; - taosArrayPush(tx, &info); + setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED); + pRuntimeEnv->scanFlag = REPEAT_SCAN; - taosArrayPush(g1, &tx); - STableGroupInfo gp = {.numOfTables = 1, .pGroupList = g1}; + if (pRuntimeEnv->pTsBuf) { + bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf); + assert(ret); + } - // include only current table - if (pRuntimeEnv->pQueryHandle != NULL) { - tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle); - pRuntimeEnv->pQueryHandle = NULL; - } + pResultRowInfo->curIndex = 0; + pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey; - pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &gp, pQInfo, &pQInfo->memRef); - taosArrayDestroy(tx); - taosArrayDestroy(g1); - if (pRuntimeEnv->pQueryHandle == NULL) { - longjmp(pRuntimeEnv->env, terrno); + qDebug("QInfo:%p start to repeat scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64, + pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey); } - if (pRuntimeEnv->pTsBuf != NULL) { - tVariant* pTag = &pRuntimeEnv->pCtx[0].tag; - - if (pRuntimeEnv->cur.vgroupIndex == -1) { - STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQInfo->vgId, pTag); - // failed to find data with the specified tag value and vnodeId - if (!tsBufIsValidElem(&elem)) { - if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qError("QInfo:%p failed to find tag:%s in ts_comp", pQInfo, pTag->pz); - } else { - qError("QInfo:%p failed to find tag:%"PRId64" in ts_comp", pQInfo, pTag->i64); - } + if (pTableScanInfo->reverseTimes > 0) { + setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput); - return false; - } else { - STSCursor cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); + STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); + tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond); - if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, - cur.blockIndex, cur.tsIndex); - } else { - qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, - cur.blockIndex, cur.tsIndex); - } - } - } else { - STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf); - if (tVariantCompare(elem.tag, &pRuntimeEnv->pCtx[0].tag) != 0) { + qDebug("QInfo:%p start to reverse scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64, + pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey); - STSElem elem1 = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQInfo->vgId, pTag); - // failed to find data with the specified tag value and vnodeId - if (!tsBufIsValidElem(&elem1)) { - if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qError("QInfo:%p failed to find tag:%s in ts_comp", pQInfo, pTag->pz); - } else { - qError("QInfo:%p failed to find tag:%"PRId64" in ts_comp", pQInfo, pTag->i64); - } + pRuntimeEnv->scanFlag = REVERSE_SCAN; - return false; - } else { - STSCursor cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); - if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, cur.blockIndex, cur.tsIndex); - } else { - qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, cur.blockIndex, cur.tsIndex); - } - } + pTableScanInfo->times = 1; + pTableScanInfo->current = 0; + pTableScanInfo->reverseTimes = 0; + pTableScanInfo->order = cond.order; - } else { - tsBufSetCursor(pRuntimeEnv->pTsBuf, &pRuntimeEnv->cur); - STSCursor cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); - if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) { - qDebug("QInfo:%p continue scan ts_comp file, tag:%s blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, cur.blockIndex, cur.tsIndex); - } else { - qDebug("QInfo:%p continue scan ts_comp file, tag:%"PRId64" blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, cur.blockIndex, cur.tsIndex); - } - } + if (pResultRowInfo->size > 0) { + pResultRowInfo->curIndex = pResultRowInfo->size-1; + pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey; + } + + SSDataBlock* p = doTableScanImpl(pOperator); + if (p != NULL) { + return p; } } - initCtxOutputBuf(pRuntimeEnv); - return true; + return NULL; } -STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) { - STsdbQueryCond cond = { - .colList = pQuery->colList, - .order = pQuery->order.order, - .numOfCols = pQuery->numOfCols, - .loadExternalRows = false, - }; +static SSDataBlock* doBlockInfoScan(void* param) { + SOperatorInfo *pOperator = (SOperatorInfo*)param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - TIME_WINDOW_COPY(cond.twindow, *win); - return cond; -} + STableScanInfo *pTableScanInfo = pOperator->info; -static STableIdInfo createTableIdInfo(SQuery* pQuery) { - assert(pQuery != NULL && pQuery->current != NULL); + STableBlockDist tableBlockDist = {0}; + tableBlockDist.numOfTables = (int32_t)pOperator->pRuntimeEnv->tableqinfoGroupInfo.numOfTables; + tableBlockDist.dataBlockInfos = taosArrayInit(512, sizeof(SFileBlockInfo)); - STableIdInfo tidInfo; - STableId* id = TSDB_TABLEID(pQuery->current->pTable); + tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist); + tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle); - tidInfo.uid = id->uid; - tidInfo.tid = id->tid; - tidInfo.key = pQuery->current->lastKey; + SSDataBlock* pBlock = &pTableScanInfo->block; + pBlock->info.rows = 1; + pBlock->info.numOfCols = 1; - return tidInfo; -} + SBufferWriter bw = tbufInitWriter(NULL, false); + blockDistInfoToBinary(&tableBlockDist, &bw); + SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0); -static void updateTableIdInfo(SQuery* pQuery, SHashObj* pTableIdInfo) { - STableIdInfo tidInfo = createTableIdInfo(pQuery); - STableIdInfo* idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid)); - if (idinfo != NULL) { - assert(idinfo->tid == tidInfo.tid && idinfo->uid == tidInfo.uid); - idinfo->key = tidInfo.key; - } else { - taosHashPut(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo)); - } -} + int32_t len = (int32_t) tbufTell(&bw); + pColInfo->pData = malloc(len + sizeof(int32_t)); -/** - * super table query handler - * 1. super table projection query, group-by on normal columns query, ts-comp query - * 2. point interpolation query, last row query - * - * @param pQInfo - */ -static void sequentialTableProcess(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; - setQueryStatus(pQuery, QUERY_COMPLETED); + *(int32_t*) pColInfo->pData = len; + memcpy(pColInfo->pData + sizeof(int32_t), tbufGetData(&bw, false), len); - size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + tbufCloseWriter(&bw); - if (isPointInterpoQuery(pQuery)) { - resetDefaultResInfoOutputBuf(pRuntimeEnv); - assert(pQuery->limit.offset == 0 && pQuery->limit.limit != 0); + SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0); + pOperator->pRuntimeEnv->pQuery->current = taosArrayGetP(g, 0); - while (pQInfo->groupIndex < numOfGroups) { - SArray *group = taosArrayGetP(pQInfo->tableGroupInfo.pGroupList, pQInfo->groupIndex); + pOperator->status = OP_EXEC_DONE; + return pBlock; +} - qDebug("QInfo:%p point interpolation query on group:%d, total group:%" PRIzu ", current group:%p", pQInfo, - pQInfo->groupIndex, numOfGroups, group); - STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); +SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) { + assert(repeatTime > 0); - SArray *g1 = taosArrayInit(1, POINTER_BYTES); - SArray *tx = taosArrayDup(group); - taosArrayPush(g1, &tx); + STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo)); + pInfo->pQueryHandle = pTsdbQueryHandle; + pInfo->times = repeatTime; + pInfo->reverseTimes = 0; + pInfo->order = pRuntimeEnv->pQuery->order.order; + pInfo->current = 0; - STableGroupInfo gp = {.numOfTables = taosArrayGetSize(tx), .pGroupList = g1}; + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "TableScanOperator"; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->numOfOutput = pRuntimeEnv->pQuery->numOfCols; + pOperator->pRuntimeEnv = pRuntimeEnv; + pOperator->exec = doTableScan; - // include only current table - if (pRuntimeEnv->pQueryHandle != NULL) { - tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle); - pRuntimeEnv->pQueryHandle = NULL; - } + return pOperator; +} - pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(pQInfo->tsdb, &cond, &gp, pQInfo, &pQInfo->memRef); +SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv) { + STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo)); - taosArrayDestroy(tx); - taosArrayDestroy(g1); - if (pRuntimeEnv->pQueryHandle == NULL) { - longjmp(pRuntimeEnv->env, terrno); - } + pInfo->pQueryHandle = pTsdbQueryHandle; + pInfo->times = 1; + pInfo->reverseTimes = 0; + pInfo->order = pRuntimeEnv->pQuery->order.order; + pInfo->current = 0; - initCtxOutputBuf(pRuntimeEnv); + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "TableSeqScanOperator"; + pOperator->operatorType = OP_TableSeqScan; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->numOfOutput = pRuntimeEnv->pQuery->numOfCols; + pOperator->pRuntimeEnv = pRuntimeEnv; + pOperator->exec = doTableScanImpl; - SArray *s = tsdbGetQueriedTableList(pRuntimeEnv->pQueryHandle); - assert(taosArrayGetSize(s) >= 1); + return pOperator; +} - setTagVal(pRuntimeEnv, taosArrayGetP(s, 0)); - taosArrayDestroy(s); +SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv) { + STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo)); - // here we simply set the first table as current table - SArray *first = GET_TABLEGROUP(pQInfo, pQInfo->groupIndex); - pQuery->current = taosArrayGetP(first, 0); + pInfo->pQueryHandle = pTsdbQueryHandle; + pInfo->block.pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData)); - scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey); + SColumnInfoData infoData = {{0}}; + infoData.info.type = TSDB_DATA_TYPE_BINARY; + infoData.info.bytes = 1024; + infoData.info.colId = TSDB_BLOCK_DIST_COLUMN_INDEX; + taosArrayPush(pInfo->block.pDataBlock, &infoData); - int64_t numOfRes = getNumOfResult(pRuntimeEnv); - if (numOfRes > 0) { - pQuery->rec.rows += numOfRes; - forwardCtxOutputBuf(pRuntimeEnv, numOfRes); - } + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "TableBlockInfoScanOperator"; + pOperator->operatorType = OP_TableBlockInfoScan; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; + pOperator->numOfOutput = pRuntimeEnv->pQuery->numOfCols; + pOperator->exec = doBlockInfoScan; - skipResults(pRuntimeEnv); - pQInfo->groupIndex += 1; + return pOperator; +} - // enable execution for next table, when handling the projection query - enableExecutionForNextTable(pRuntimeEnv); +void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) { + assert(pTableScanInfo != NULL && pDownstream != NULL); - if (pQuery->rec.rows >= pQuery->rec.capacity) { - setQueryStatus(pQuery, QUERY_RESBUF_FULL); - break; - } - } - } else if (pRuntimeEnv->groupbyColumn) { // group-by on normal columns query - while (pQInfo->groupIndex < numOfGroups) { - SArray *group = taosArrayGetP(pQInfo->tableGroupInfo.pGroupList, pQInfo->groupIndex); + pTableScanInfo->pExpr = pDownstream->pExpr; // TODO refactor to use colId instead of pExpr + pTableScanInfo->numOfOutput = pDownstream->numOfOutput; - qDebug("QInfo:%p group by normal columns group:%d, total group:%" PRIzu "", pQInfo, pQInfo->groupIndex, - numOfGroups); + if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) { + SAggOperatorInfo* pAggInfo = pDownstream->info; - STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); + pTableScanInfo->pCtx = pAggInfo->binfo.pCtx; + pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo; + pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset; + } else if (pDownstream->operatorType == OP_TimeInterval) { + STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info; - SArray *g1 = taosArrayInit(1, POINTER_BYTES); - SArray *tx = taosArrayDup(group); - taosArrayPush(g1, &tx); + pTableScanInfo->pCtx = pIntervalInfo->pCtx; + pTableScanInfo->pResultRowInfo = &pIntervalInfo->resultRowInfo; + pTableScanInfo->rowCellInfoOffset = pIntervalInfo->rowCellInfoOffset; - STableGroupInfo gp = {.numOfTables = taosArrayGetSize(tx), .pGroupList = g1}; + } else if (pDownstream->operatorType == OP_Groupby) { + SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info; - // include only current table - if (pRuntimeEnv->pQueryHandle != NULL) { - tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle); - pRuntimeEnv->pQueryHandle = NULL; - } + pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx; + pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo; + pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset; - // no need to update the lastkey for each table - pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &gp, pQInfo, &pQInfo->memRef); + } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) { + STableIntervalOperatorInfo *pInfo = pDownstream->info; - taosArrayDestroy(g1); - taosArrayDestroy(tx); - if (pRuntimeEnv->pQueryHandle == NULL) { - longjmp(pRuntimeEnv->env, terrno); - } + pTableScanInfo->pCtx = pInfo->pCtx; + pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo; + pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset; - SArray *s = tsdbGetQueriedTableList(pRuntimeEnv->pQueryHandle); - assert(taosArrayGetSize(s) >= 1); + } else if (pDownstream->operatorType == OP_Arithmetic) { + SArithOperatorInfo *pInfo = pDownstream->info; + + pTableScanInfo->pCtx = pInfo->binfo.pCtx; + pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo; + pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset; + } else { + assert(0); + } +} - setTagVal(pRuntimeEnv, taosArrayGetP(s, 0)); +static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) { + assert(repeatTime > 0); - // here we simply set the first table as current table - scanMultiTableDataBlocks(pQInfo); - pQInfo->groupIndex += 1; + STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo)); + pInfo->pQueryHandle = pTsdbQueryHandle; + pInfo->times = repeatTime; + pInfo->reverseTimes = reverseTime; + pInfo->current = 0; + pInfo->order = pRuntimeEnv->pQuery->order.order; - taosArrayDestroy(s); + SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo)); + pOptr->name = "DataBlocksOptimizedScanOperator"; + pOptr->operatorType = OP_DataBlocksOptScan; + pOptr->pRuntimeEnv = pRuntimeEnv; + pOptr->blockingOptr = false; + pOptr->info = pInfo; + pOptr->exec = doTableScan; - // no results generated for current group, continue to try the next group - SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; - if (pWindowResInfo->size <= 0) { - continue; - } + return pOptr; +} - for (int32_t i = 0; i < pWindowResInfo->size; ++i) { - pWindowResInfo->pResult[i]->closed = true; // enable return all results for group by normal columns +static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) { + return pTableScanInfo->order; +} - SResultRow *pResult = pWindowResInfo->pResult[i]; - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - SResultRowCellInfo *pCell = getResultCell(pRuntimeEnv, pResult, j); - pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes)); - } - } +// this is a blocking operator +static SSDataBlock* doAggregate(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - qDebug("QInfo:%p generated groupby columns results %d rows for group %d completed", pQInfo, pWindowResInfo->size, - pQInfo->groupIndex); + SAggOperatorInfo* pAggInfo = pOperator->info; + SOptrBasicInfo* pInfo = &pAggInfo->binfo; - pQuery->rec.rows = 0; - if (pWindowResInfo->size > pQuery->rec.capacity) { - expandBuffer(pRuntimeEnv, pWindowResInfo->size, pQInfo); - } + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; - initGroupResInfo(&pQInfo->groupResInfo, &pRuntimeEnv->resultRowInfo, 0); - copyToOutputBuf(pQInfo, pWindowResInfo); - assert(pQuery->rec.rows == pWindowResInfo->size); + SQuery* pQuery = pRuntimeEnv->pQuery; + int32_t order = pQuery->order.order; + + SOperatorInfo* upstream = pOperator->upstream; - resetResultRowInfo(pRuntimeEnv, &pRuntimeEnv->resultRowInfo); - cleanupGroupResInfo(&pQInfo->groupResInfo); + while(1) { + SSDataBlock* pBlock = upstream->exec(upstream); + if (pBlock == NULL) { break; } - } else if (pRuntimeEnv->queryWindowIdentical && pRuntimeEnv->pTsBuf == NULL && !isTsCompQuery(pQuery)) { - //super table projection query with identical query time range for all tables. - SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; - resetDefaultResInfoOutputBuf(pRuntimeEnv); - SArray *group = GET_TABLEGROUP(pQInfo, 0); - assert(taosArrayGetSize(group) == pQInfo->tableqinfoGroupInfo.numOfTables && - 1 == taosArrayGetSize(pQInfo->tableqinfoGroupInfo.pGroupList)); + setTagValue(pOperator, pQuery->current->pTable, pInfo->pCtx, pOperator->numOfOutput); - void *pQueryHandle = pRuntimeEnv->pQueryHandle; - if (pQueryHandle == NULL) { - STsdbQueryCond con = createTsdbQueryCond(pQuery, &pQuery->window); - pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQInfo->tsdb, &con, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); - pQueryHandle = pRuntimeEnv->pQueryHandle; + if (upstream->operatorType == OP_DataBlocksOptScan) { + STableScanInfo* pScanInfo = upstream->info; + order = getTableScanOrder(pScanInfo); } - // skip blocks without load the actual data block from file if no filter condition present - // skipBlocks(&pQInfo->runtimeEnv); - // if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0) { - // setQueryStatus(pQuery, QUERY_COMPLETED); - // return; - // } + // the pDataBlock are always the same one, no need to call this again + setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); + doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock); + } - if (pQuery->prjInfo.vgroupLimit != -1) { - assert(pQuery->limit.limit == -1 && pQuery->limit.offset == 0); - } else if (pQuery->limit.limit != -1) { - assert(pQuery->prjInfo.vgroupLimit == -1); - } + pOperator->status = OP_EXEC_DONE; + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); + finalizeQueryResult(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset); + pInfo->pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); - bool hasMoreBlock = true; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); - SQueryCostInfo *summary = &pRuntimeEnv->summary; - while ((hasMoreBlock = tsdbNextDataBlock(pQueryHandle)) == true) { - summary->totalBlocks += 1; + return pInfo->pRes; +} - if (isQueryKilled(pQInfo)) { - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } +static SSDataBlock* doSTableAggregate(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo); - STableQueryInfo **pTableQueryInfo = - (STableQueryInfo **) taosHashGet(pQInfo->tableqinfoGroupInfo.map, &blockInfo.tid, sizeof(blockInfo.tid)); - if (pTableQueryInfo == NULL) { - break; - } + SAggOperatorInfo* pAggInfo = pOperator->info; + SOptrBasicInfo* pInfo = &pAggInfo->binfo; - pQuery->current = *pTableQueryInfo; - doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo); + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; - if (pRuntimeEnv->hasTagResults) { - setTagVal(pRuntimeEnv, pQuery->current->pTable); - } + if (pOperator->status == OP_RES_TO_RETURN) { + toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes); - if (pQuery->prjInfo.vgroupLimit > 0 && pQuery->current->resInfo.size > pQuery->prjInfo.vgroupLimit) { - pQuery->current->lastKey = - QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step; - continue; - } + if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; + } - // it is a super table ordered projection query, check for the number of output for each vgroup - if (pQuery->prjInfo.vgroupLimit > 0 && pQuery->rec.rows >= pQuery->prjInfo.vgroupLimit) { - if (QUERY_IS_ASC_QUERY(pQuery) && blockInfo.window.skey >= pQuery->prjInfo.ts) { - pQuery->current->lastKey = - QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step; - continue; - } else if (!QUERY_IS_ASC_QUERY(pQuery) && blockInfo.window.ekey <= pQuery->prjInfo.ts) { - pQuery->current->lastKey = - QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step; - continue; - } - } + return pInfo->pRes; + } - uint32_t status = 0; - SDataStatis *pStatis = NULL; - SArray *pDataBlock = NULL; + SQuery* pQuery = pRuntimeEnv->pQuery; + int32_t order = pQuery->order.order; - int32_t ret = loadDataBlockOnDemand(pRuntimeEnv, &pQuery->current->resInfo, pQueryHandle, &blockInfo, - &pStatis, &pDataBlock, &status); - if (ret != TSDB_CODE_SUCCESS) { - break; - } + SOperatorInfo* upstream = pOperator->upstream; - if(status == BLK_DATA_DISCARD) { - pQuery->current->lastKey = - QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step; - continue; - } + while(1) { + SSDataBlock* pBlock = upstream->exec(upstream); + if (pBlock == NULL) { + break; + } - ensureOutputBuffer(pRuntimeEnv, blockInfo.rows); - int64_t prev = getNumOfResult(pRuntimeEnv); + setTagValue(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->pCtx, pOperator->numOfOutput); - pQuery->pos = QUERY_IS_ASC_QUERY(pQuery) ? 0 : blockInfo.rows - 1; - int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, binarySearchForKey, pDataBlock); + if (upstream->operatorType == OP_DataBlocksOptScan) { + STableScanInfo* pScanInfo = upstream->info; + order = getTableScanOrder(pScanInfo); + } - summary->totalRows += blockInfo.rows; - qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64, - GET_QINFO_ADDR(pRuntimeEnv), blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, numOfRes, - pQuery->current->lastKey); + // the pDataBlock are always the same one, no need to call this again + setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); - pQuery->rec.rows = getNumOfResult(pRuntimeEnv); + TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1; + setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pQuery->current->groupIndex, key); + doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock); + } - int64_t inc = pQuery->rec.rows - prev; - pQuery->current->resInfo.size += (int32_t) inc; + pOperator->status = OP_RES_TO_RETURN; + closeAllResultRows(&pInfo->resultRowInfo); - // the flag may be set by tableApplyFunctionsOnBlock, clear it here - CLEAR_QUERY_STATUS(pQuery, QUERY_COMPLETED); + updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo, + pInfo->rowCellInfoOffset); - updateTableIdInfo(pQuery, pQInfo->arrTableIdInfo); + initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->resultRowInfo); - if (pQuery->prjInfo.vgroupLimit >= 0) { - if (((pQuery->rec.rows + pQuery->rec.total) < pQuery->prjInfo.vgroupLimit) || ((pQuery->rec.rows + pQuery->rec.total) > pQuery->prjInfo.vgroupLimit && prev < pQuery->prjInfo.vgroupLimit)) { - if (QUERY_IS_ASC_QUERY(pQuery) && pQuery->prjInfo.ts < blockInfo.window.ekey) { - pQuery->prjInfo.ts = blockInfo.window.ekey; - } else if (!QUERY_IS_ASC_QUERY(pQuery) && pQuery->prjInfo.ts > blockInfo.window.skey) { - pQuery->prjInfo.ts = blockInfo.window.skey; - } - } - } else { - // the limitation of output result is reached, set the query completed - skipResults(pRuntimeEnv); - if (limitOperator(pQuery, pQInfo)) { - SET_STABLE_QUERY_OVER(pQInfo); - break; - } - } + toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes); + if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; + } - // while the output buffer is full or limit/offset is applied, query may be paused here - if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL|QUERY_COMPLETED)) { - break; - } - } + return pInfo->pRes; +} - if (!hasMoreBlock) { - setQueryStatus(pQuery, QUERY_COMPLETED); - SET_STABLE_QUERY_OVER(pQInfo); - } - } else { - /* - * the following two cases handled here. - * 1. ts-comp query, and 2. the super table projection query with different query time range for each table. - * If the subgroup index is larger than 0, results generated by group by tbname,k is existed. - * we need to return it to client in the first place. - */ - if (hasRemainData(&pQInfo->groupResInfo)) { - copyToOutputBuf(pQInfo, &pRuntimeEnv->resultRowInfo); - pQuery->rec.total += pQuery->rec.rows; +static SSDataBlock* doArithmeticOperation(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; - if (pQuery->rec.rows > 0) { - return; - } + SArithOperatorInfo* pArithInfo = pOperator->info; + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + SOptrBasicInfo *pInfo = &pArithInfo->binfo; + + SSDataBlock* pRes = pInfo->pRes; + int32_t order = pRuntimeEnv->pQuery->order.order; + + pRes->info.rows = 0; + + while(1) { + SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream); + if (pBlock == NULL) { + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); + break; } - // all data have returned already - if (pQInfo->tableIndex >= pQInfo->tableqinfoGroupInfo.numOfTables) { - return; + STableQueryInfo* pTableQueryInfo = pRuntimeEnv->pQuery->current; + + // todo dynamic set tags + setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput); + + // the pDataBlock are always the same one, no need to call this again + setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); + updateOutputBuf(pArithInfo, pBlock->info.rows); + + arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); + updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order); + + pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); + if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) { + break; } + } - resetDefaultResInfoOutputBuf(pRuntimeEnv); - resetResultRowInfo(pRuntimeEnv, &pRuntimeEnv->resultRowInfo); + clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput); + return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL; +} - SArray *group = GET_TABLEGROUP(pQInfo, 0); - assert(taosArrayGetSize(group) == pQInfo->tableqinfoGroupInfo.numOfTables && - 1 == taosArrayGetSize(pQInfo->tableqinfoGroupInfo.pGroupList)); +static SSDataBlock* doLimit(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - while (pQInfo->tableIndex < pQInfo->tableqinfoGroupInfo.numOfTables) { - if (isQueryKilled(pQInfo)) { - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } + SLimitOperatorInfo* pInfo = pOperator->info; - pQuery->current = taosArrayGetP(group, pQInfo->tableIndex); - if (!multiTableMultioutputHelper(pQInfo, pQInfo->tableIndex)) { - pQInfo->tableIndex++; - continue; - } + SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream); + if (pBlock == NULL) { + setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); + pOperator->status = OP_EXEC_DONE; + return NULL; + } - // TODO handle the limit offset problem - if (pQuery->numOfFilterCols == 0 && pQuery->limit.offset > 0) { - if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - pQInfo->tableIndex++; - continue; - } - } + if (pInfo->total + pBlock->info.rows >= pInfo->limit) { + pBlock->info.rows = (int32_t) (pInfo->limit - pInfo->total); - scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey); - skipResults(pRuntimeEnv); + pInfo->total = pInfo->limit; - // the limitation of output result is reached, set the query completed - if (limitOperator(pQuery, pQInfo)) { - SET_STABLE_QUERY_OVER(pQInfo); - break; - } + setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); + pOperator->status = OP_EXEC_DONE; + } else { + pInfo->total += pBlock->info.rows; + } - // enable execution for next table, when handling the projection query - enableExecutionForNextTable(pRuntimeEnv); - - if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - /* - * query range is identical in terms of all meters involved in query, - * so we need to restore them at the *beginning* of query on each meter, - * not the consecutive query on meter on which is aborted due to buffer limitation - * to ensure that, we can reset the query range once query on a meter is completed. - */ - pQInfo->tableIndex++; - updateTableIdInfo(pQuery, pQInfo->arrTableIdInfo); - - // if the buffer is full or group by each table, we need to jump out of the loop - if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)) { - break; - } + return pBlock; +} - if (pRuntimeEnv->pTsBuf != NULL) { - pRuntimeEnv->cur = pRuntimeEnv->pTsBuf->cur; - } +// TODO add log +static SSDataBlock* doOffset(void* param) { + SOperatorInfo *pOperator = (SOperatorInfo *)param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - } else { - // all data in the result buffer are skipped due to the offset, continue to retrieve data from current meter - if (pQuery->rec.rows == 0) { - assert(!Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)); - continue; - } else { - // buffer is full, wait for the next round to retrieve data from current meter - assert(Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)); - break; - } - } - } + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; - if (pQInfo->tableIndex >= pQInfo->tableqinfoGroupInfo.numOfTables) { - setQueryStatus(pQuery, QUERY_COMPLETED); + while (1) { + SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream); + if (pBlock == NULL) { + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); + pOperator->status = OP_EXEC_DONE; + return NULL; } - /* - * 1. super table projection query, group-by on normal columns query, ts-comp query - * 2. point interpolation query, last row query - * - * group-by on normal columns query and last_row query do NOT invoke the finalizer here, - * since the finalize stage will be done at the client side. - * - * projection query, point interpolation query do not need the finalizer. - * - * Only the ts-comp query requires the finalizer function to be executed here. - */ - if (isTsCompQuery(pQuery)) { - finalizeQueryResult(pRuntimeEnv); - } + if (pRuntimeEnv->currentOffset == 0) { + return pBlock; + } else if (pRuntimeEnv->currentOffset > pBlock->info.rows) { + pRuntimeEnv->currentOffset -= pBlock->info.rows; + } else { + int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset); + pBlock->info.rows = remain; - if (pRuntimeEnv->pTsBuf != NULL) { - pRuntimeEnv->cur = pRuntimeEnv->pTsBuf->cur; - } + for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) { + SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, i); - qDebug("QInfo %p numOfTables:%" PRIu64 ", index:%d, numOfGroups:%" PRIzu ", %" PRId64 - " points returned, total:%" PRId64 ", offset:%" PRId64, - pQInfo, (uint64_t)pQInfo->tableqinfoGroupInfo.numOfTables, pQInfo->tableIndex, numOfGroups, pQuery->rec.rows, - pQuery->rec.total, pQuery->limit.offset); + int16_t bytes = pColInfoData->info.bytes; + memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes); + } + + pRuntimeEnv->currentOffset = 0; + return pBlock; + } } } -static int32_t doSaveContext(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; +static SSDataBlock* doIntervalAgg(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - SET_REVERSE_SCAN_FLAG(pRuntimeEnv); - SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); - SWITCH_ORDER(pQuery->order.order); + STableIntervalOperatorInfo* pIntervalInfo = pOperator->info; - if (pRuntimeEnv->pTsBuf != NULL) { - SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order); - } + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + if (pOperator->status == OP_RES_TO_RETURN) { + toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); - STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window); + if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; + } - // clean unused handle - if (pRuntimeEnv->pSecQueryHandle != NULL) { - tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); + return pIntervalInfo->pRes; } - setQueryStatus(pQuery, QUERY_NOT_COMPLETED); - switchCtxOrder(pRuntimeEnv); - disableFuncInReverseScan(pQInfo); - setupQueryRangeForReverseScan(pQInfo); - - pRuntimeEnv->prevGroupId = INT32_MIN; - pRuntimeEnv->pSecQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo, &pQInfo->memRef); - return (pRuntimeEnv->pSecQueryHandle == NULL)? -1:0; -} + SQuery* pQuery = pRuntimeEnv->pQuery; + int32_t order = pQuery->order.order; + STimeWindow win = pQuery->window; -static void doRestoreContext(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; + SOperatorInfo* upstream = pOperator->upstream; - SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); - SWITCH_ORDER(pQuery->order.order); + while(1) { + SSDataBlock* pBlock = upstream->exec(upstream); + if (pBlock == NULL) { + break; + } - if (pRuntimeEnv->pTsBuf != NULL) { - SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order); + // the pDataBlock are always the same one, no need to call this again + setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order); + hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0); } - switchCtxOrder(pRuntimeEnv); - SET_MASTER_SCAN_FLAG(pRuntimeEnv); -} + // restore the value + pQuery->order.order = order; + pQuery->window = win; -static void doCloseAllTimeWindow(SQInfo *pQInfo) { - SQuery *pQuery = pQInfo->runtimeEnv.pQuery; + pOperator->status = OP_RES_TO_RETURN; + closeAllResultRows(&pIntervalInfo->resultRowInfo); + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); + finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset); - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pQInfo); - for (int32_t i = 0; i < numOfGroup; ++i) { - SArray *group = GET_TABLEGROUP(pQInfo, i); - - size_t num = taosArrayGetSize(group); - for (int32_t j = 0; j < num; ++j) { - STableQueryInfo* item = taosArrayGetP(group, j); - closeAllResultRows(&item->resInfo); - } - } - } else { // close results for group result - closeAllResultRows(&pQInfo->runtimeEnv.resultRowInfo); + initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo); + toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); + + if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; } + + return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes; } -static void multiTableQueryProcess(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery *pQuery = pRuntimeEnv->pQuery; +static SSDataBlock* doSTableIntervalAgg(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } - if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { - copyResToQueryResultBuf(pQInfo, pQuery); - } else { - copyToOutputBuf(pQInfo, &pRuntimeEnv->resultRowInfo); + STableIntervalOperatorInfo* pIntervalInfo = pOperator->info; + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + + if (pOperator->status == OP_RES_TO_RETURN) { + copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset); + if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; } - qDebug("QInfo:%p current:%"PRId64", total:%"PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total); - return; + return pIntervalInfo->pRes; } - qDebug("QInfo:%p query start, qrange:%" PRId64 "-%" PRId64 ", order:%d, forward scan start", pQInfo, - pQuery->window.skey, pQuery->window.ekey, pQuery->order.order); + SQuery* pQuery = pRuntimeEnv->pQuery; + int32_t order = pQuery->order.order; - // do check all qualified data blocks - int64_t el = scanMultiTableDataBlocks(pQInfo); - qDebug("QInfo:%p master scan completed, elapsed time: %" PRId64 "ms, reverse scan start", pQInfo, el); + SOperatorInfo* upstream = pOperator->upstream; - // query error occurred or query is killed, abort current execution - if (pQInfo->code != TSDB_CODE_SUCCESS || isQueryKilled(pQInfo)) { - qDebug("QInfo:%p query killed or error occurred, code:%s, abort", pQInfo, tstrerror(pQInfo->code)); - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } + while(1) { + SSDataBlock* pBlock = upstream->exec(upstream); + if (pBlock == NULL) { + break; + } - // close all time window results - doCloseAllTimeWindow(pQInfo); + // the pDataBlock are always the same one, no need to call this again + STableQueryInfo* pTableQueryInfo = pRuntimeEnv->pQuery->current; - if (needReverseScan(pQuery)) { - int32_t code = doSaveContext(pQInfo); - if (code == TSDB_CODE_SUCCESS) { - el = scanMultiTableDataBlocks(pQInfo); - qDebug("QInfo:%p reversed scan completed, elapsed time: %" PRId64 "ms", pQInfo, el); - doRestoreContext(pQInfo); - } else { - pQInfo->code = code; - } - } else { - qDebug("QInfo:%p no need to do reversed scan, query completed", pQInfo); + setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput); + setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order); + setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey); + + hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex); } - setQueryStatus(pQuery, QUERY_COMPLETED); + pOperator->status = OP_RES_TO_RETURN; + pQuery->order.order = order; // TODO : restore the order + doCloseAllTimeWindow(pRuntimeEnv); + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); - if (pQInfo->code != TSDB_CODE_SUCCESS || isQueryKilled(pQInfo)) { - qDebug("QInfo:%p query killed or error occurred, code:%s, abort", pQInfo, tstrerror(pQInfo->code)); - //TODO finalizeQueryResult may cause SEGSEV, since the memory may not allocated yet, add a cleanup function instead - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); + copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset); + if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; } - if (QUERY_IS_INTERVAL_QUERY(pQuery) || isSumAvgRateQuery(pQuery)) { - copyResToQueryResultBuf(pQInfo, pQuery); - } else { // not a interval query - initGroupResInfo(&pQInfo->groupResInfo, &pRuntimeEnv->resultRowInfo, 0); - copyToOutputBuf(pQInfo, &pRuntimeEnv->resultRowInfo); + return pIntervalInfo->pRes; +} + +static SSDataBlock* hashGroupbyAggregate(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; } - // handle the limitation of output buffer - qDebug("QInfo:%p points returned:%" PRId64 ", total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows); -} + SGroupbyOperatorInfo *pInfo = pOperator->info; + + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + if (pOperator->status == OP_RES_TO_RETURN) { + toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes); -static char *getArithemicInputSrc(void *param, const char *name, int32_t colId) { - SArithmeticSupport *pSupport = (SArithmeticSupport *) param; - SExprInfo* pExprInfo = (SExprInfo*) pSupport->exprList; + if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; + } + + return pInfo->binfo.pRes; + } - int32_t index = -1; - for (int32_t i = 0; i < pSupport->numOfCols; ++i) { - if (colId == pExprInfo[i].base.resColId) { - index = i; + SOperatorInfo* upstream = pOperator->upstream; + + while(1) { + SSDataBlock* pBlock = upstream->exec(upstream); + if (pBlock == NULL) { break; } + + // the pDataBlock are always the same one, no need to call this again + setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQuery->order.order); + setTagValue(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput); + if (pInfo->colIndex == -1) { + pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock); + } + + doHashGroupbyAgg(pOperator, pInfo, pBlock); } - assert(index >= 0 && index < pSupport->numOfCols); - return pSupport->data[index] + pSupport->offset * pExprInfo[index].bytes; -} + pOperator->status = OP_RES_TO_RETURN; + closeAllResultRows(&pInfo->binfo.resultRowInfo); + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); -static void doSecondaryArithmeticProcess(SQuery* pQuery) { - if (pQuery->numOfExpr2 == 0) { - return; + if (!pRuntimeEnv->pQuery->stableQuery) { // finalize include the update of result rows + finalizeQueryResult(pOperator, pInfo->binfo.pCtx, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset); + } else { + updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset); } - SArithmeticSupport arithSup = {0}; - tFilePage **data = calloc(pQuery->numOfExpr2, POINTER_BYTES); - for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) { - int32_t bytes = pQuery->pExpr2[i].bytes; - data[i] = (tFilePage *)malloc((size_t)(bytes * pQuery->rec.rows) + sizeof(tFilePage)); + initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo); + toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes); + + if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { + pOperator->status = OP_EXEC_DONE; } - arithSup.offset = 0; - arithSup.numOfCols = (int32_t)pQuery->numOfOutput; - arithSup.exprList = pQuery->pExpr1; - arithSup.data = calloc(arithSup.numOfCols, POINTER_BYTES); + return pInfo->binfo.pRes; +} - for (int32_t k = 0; k < arithSup.numOfCols; ++k) { - arithSup.data[k] = pQuery->sdata[k]->data; +static SSDataBlock* doFill(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; } - for (int i = 0; i < pQuery->numOfExpr2; ++i) { - SExprInfo *pExpr = &pQuery->pExpr2[i]; + SFillOperatorInfo *pInfo = pOperator->info; + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; - // calculate the result from several other columns - SSqlFuncMsg* pSqlFunc = &pExpr->base; - if (pSqlFunc->functionId != TSDB_FUNC_ARITHM) { + if (taosFillHasMoreResults(pInfo->pFillInfo)) { + doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity); + return pInfo->pRes; + } - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - if (pSqlFunc->functionId == pQuery->pExpr1[j].base.functionId && - pSqlFunc->colInfo.colId == pQuery->pExpr1[j].base.colInfo.colId) { - memcpy(data[i]->data, pQuery->sdata[j]->data, (size_t)(pQuery->pExpr1[j].bytes * pQuery->rec.rows)); - break; - } + while(1) { + SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream); + if (pBlock == NULL) { + if (pInfo->totalInputRows == 0) { + pOperator->status = OP_EXEC_DONE; + return NULL; } + + taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey); } else { - arithSup.pArithExpr = pExpr; - arithmeticTreeTraverse(arithSup.pArithExpr->pExpr, (int32_t)pQuery->rec.rows, data[i]->data, &arithSup, TSDB_ORDER_ASC, - getArithemicInputSrc); + pInfo->totalInputRows += pBlock->info.rows; + + int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQuery->window.ekey:pBlock->info.window.ekey; + + taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey); + taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock); } - } - for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) { - memcpy(pQuery->sdata[i]->data, data[i]->data, (size_t)(pQuery->pExpr2[i].bytes * pQuery->rec.rows)); + doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); + return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL; } +} - for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) { - tfree(data[i]); +// todo set the attribute of query scan count +static int32_t getNumOfScanTimes(SQuery* pQuery) { + for(int32_t i = 0; i < pQuery->numOfOutput; ++i) { + int32_t functionId = pQuery->pExpr1[i].base.functionId; + if (functionId == TSDB_FUNC_STDDEV || functionId == TSDB_FUNC_PERCT) { + return 2; + } } - tfree(data); - tfree(arithSup.data); + return 1; } -/* - * in each query, this function will be called only once, no retry for further result. - * - * select count(*)/top(field,k)/avg(field name) from table_name [where ts>now-1a]; - * select count(*) from table_name group by status_column; - */ -static void tableAggregationProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - - SQuery *pQuery = pRuntimeEnv->pQuery; - if (!pRuntimeEnv->topBotQuery && pQuery->limit.offset > 0) { // no need to execute, since the output will be ignore. +static void destroyOperatorInfo(SOperatorInfo* pOperator) { + if (pOperator == NULL) { return; } - scanOneTableDataBlocks(pRuntimeEnv, pTableInfo->lastKey); - finalizeQueryResult(pRuntimeEnv); + if (pOperator->cleanup != NULL) { + pOperator->cleanup(pOperator->info, pOperator->numOfOutput); + } - // since the numOfRows must be identical for all sql functions that are allowed to be executed simutaneously. - pQuery->rec.rows = getNumOfResult(pRuntimeEnv); - doSecondaryArithmeticProcess(pQuery); + destroyOperatorInfo(pOperator->upstream); + tfree(pOperator->info); + tfree(pOperator); +} - if (isQueryKilled(pQInfo)) { - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); - } +static SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { + SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo)); - // TODO limit/offset refactor to be one operator - skipResults(pRuntimeEnv); - limitOperator(pQuery, pQInfo); + SQuery* pQuery = pRuntimeEnv->pQuery; + int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery)); + + pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows); + pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); + + initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT); + + pInfo->seed = rand(); + setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed); + + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "TableAggregate"; + pOperator->operatorType = OP_Aggregate; + pOperator->blockingOptr = true; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->pRuntimeEnv = pRuntimeEnv; + + pOperator->exec = doAggregate; + pOperator->cleanup = destroyBasicOperatorInfo; + return pOperator; } -static void tableProjectionProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; +static void doDestroyBasicInfo(SOptrBasicInfo* pInfo, int32_t numOfOutput) { + assert(pInfo != NULL); - // for ts_comp query, re-initialized is not allowed - SQuery *pQuery = pRuntimeEnv->pQuery; - if (!isTsCompQuery(pQuery)) { - resetDefaultResInfoOutputBuf(pRuntimeEnv); - } + destroySQLFunctionCtx(pInfo->pCtx, numOfOutput); + tfree(pInfo->rowCellInfoOffset); - // skip blocks without load the actual data block from file if no filter condition present - skipBlocks(&pQInfo->runtimeEnv); - if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0) { - setQueryStatus(pQuery, QUERY_COMPLETED); - return; - } + cleanupResultRowInfo(&pInfo->resultRowInfo); + pInfo->pRes = destroyOutputBuf(pInfo->pRes); +} - while (1) { - scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey); - finalizeQueryResult(pRuntimeEnv); +static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput) { + SOptrBasicInfo* pInfo = (SOptrBasicInfo*) param; + doDestroyBasicInfo(pInfo, numOfOutput); +} - pQuery->rec.rows = getNumOfResult(pRuntimeEnv); - if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols > 0 && pQuery->rec.rows > 0) { - skipResults(pRuntimeEnv); - } +static void destroySFillOperatorInfo(void* param, int32_t numOfOutput) { + SFillOperatorInfo* pInfo = (SFillOperatorInfo*) param; + pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo); + pInfo->pRes = destroyOutputBuf(pInfo->pRes); +} - /* - * 1. if pQuery->size == 0, pQuery->limit.offset >= 0, still need to check data - * 2. if pQuery->size > 0, pQuery->limit.offset must be 0 - */ - if (pQuery->rec.rows > 0 || Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - break; - } +static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) { + SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param; + doDestroyBasicInfo(&pInfo->binfo, numOfOutput); + tfree(pInfo->prevData); +} - qDebug("QInfo:%p skip current result, offset:%" PRId64 ", next qrange:%" PRId64 "-%" PRId64, - pQInfo, pQuery->limit.offset, pQuery->current->lastKey, pQuery->current->win.ekey); +static void destroyArithOperatorInfo(void* param, int32_t numOfOutput) { + SArithOperatorInfo* pInfo = (SArithOperatorInfo*) param; + doDestroyBasicInfo(&pInfo->binfo, numOfOutput); +} - resetDefaultResInfoOutputBuf(pRuntimeEnv); - } +static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) { + STagScanInfo* pInfo = (STagScanInfo*) param; + pInfo->pRes = destroyOutputBuf(pInfo->pRes); +} - limitOperator(pQuery, pQInfo); - if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)) { - qDebug("QInfo:%p query paused due to output limitation, next qrange:%" PRId64 "-%" PRId64, pQInfo, - pQuery->current->lastKey, pQuery->window.ekey); - } else if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - STableIdInfo tidInfo = createTableIdInfo(pQuery); - taosHashPut(pQInfo->arrTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo)); - } +SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { + SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo)); - if (!isTsCompQuery(pQuery)) { - assert(pQuery->rec.rows <= pQuery->rec.capacity); - } + size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv); + + pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) tableGroup); + pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); + initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)tableGroup, TSDB_DATA_TYPE_INT); + + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "MultiTableAggregate"; + pOperator->operatorType = OP_MultiTableAggregate; + pOperator->blockingOptr = true; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->pRuntimeEnv = pRuntimeEnv; + + pOperator->exec = doSTableAggregate; + pOperator->cleanup = destroyBasicOperatorInfo; + + return pOperator; } -static void copyAndFillResult(SQInfo* pQInfo) { - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery* pQuery = pRuntimeEnv->pQuery; +SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { + SArithOperatorInfo* pInfo = calloc(1, sizeof(SArithOperatorInfo)); - while(1) { - copyToOutputBuf(pQInfo, &pRuntimeEnv->resultRowInfo); - doSecondaryArithmeticProcess(pQuery); + pInfo->seed = rand(); + pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity; - TSKEY lastKey = 0; - if (!hasRemainData(&pQInfo->groupResInfo)) { - lastKey = pQuery->window.ekey; - } else { - lastKey = ((TSKEY*)pQuery->sdata[0]->data)[pQuery->rec.rows - 1]; - } + SOptrBasicInfo* pBInfo = &pInfo->binfo; + pBInfo->pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity); + pBInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset); - assert(lastKey <= pQuery->window.ekey); + initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT); + setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed); - taosFillSetStartInfo(pRuntimeEnv->pFillInfo, (int32_t)pQuery->rec.rows, lastKey); - taosFillSetDataBlockFromFilePage(pRuntimeEnv->pFillInfo, (const tFilePage **)pQuery->sdata); + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "ArithmeticOperator"; + pOperator->operatorType = OP_Arithmetic; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->pRuntimeEnv = pRuntimeEnv; - pQuery->rec.rows = doFillGapsInResults(pRuntimeEnv, (tFilePage **)pQuery->sdata); + pOperator->exec = doArithmeticOperation; + pOperator->cleanup = destroyArithOperatorInfo; - if (pQuery->rec.rows > 0) { - limitOperator(pQuery, pQInfo); - break; - } + return pOperator; +} - // here the pQuery->rec.rows == 0 - if (!hasRemainData(&pQInfo->groupResInfo) && !taosFillHasMoreResults(pRuntimeEnv->pFillInfo)) { - break; - } - } +SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) { + SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo)); + pInfo->limit = pRuntimeEnv->pQuery->limit.limit; + + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + + pOperator->name = "LimitOperator"; + pOperator->operatorType = OP_Limit; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->upstream = upstream; + pOperator->exec = doLimit; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; + + return pOperator; } -// handle time interval query on table -static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &(pQInfo->runtimeEnv); - SQuery *pQuery = pRuntimeEnv->pQuery; +SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) { + SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo)); - TSKEY newStartKey = QUERY_IS_ASC_QUERY(pQuery)? INT64_MIN:INT64_MAX; + pInfo->offset = pRuntimeEnv->pQuery->limit.offset; + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); - // skip blocks without load the actual data block from file if no filter condition present - if (!pRuntimeEnv->groupbyColumn) { - skipTimeInterval(pRuntimeEnv, &newStartKey); - if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0 && pRuntimeEnv->pFillInfo == NULL) { - setQueryStatus(pQuery, QUERY_COMPLETED); - return; - } - } + pOperator->name = "OffsetOperator"; + pOperator->operatorType = OP_Offset; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->upstream = upstream; + pOperator->exec = doOffset; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; - scanOneTableDataBlocks(pRuntimeEnv, newStartKey); - finalizeQueryResult(pRuntimeEnv); + return pOperator; +} - // skip offset result rows - pQuery->rec.rows = 0; +SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { + STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo)); - // not fill or no result generated during this query - if (pQuery->fillType == TSDB_FILL_NONE || pRuntimeEnv->resultRowInfo.size == 0 || isPointInterpoQuery(pQuery)) { - // all data scanned, the group by normal column can return - int32_t numOfClosed = numOfClosedResultRows(&pRuntimeEnv->resultRowInfo); - if (pQuery->limit.offset > numOfClosed || numOfClosed == 0) { - return; - } + pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset); + pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); + initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT); - initGroupResInfo(&pQInfo->groupResInfo, &pRuntimeEnv->resultRowInfo, (int32_t) pQuery->limit.offset); - copyToOutputBuf(pQInfo, &pRuntimeEnv->resultRowInfo); - doSecondaryArithmeticProcess(pQuery); + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); - limitOperator(pQuery, pQInfo); - } else { - initGroupResInfo(&pQInfo->groupResInfo, &pRuntimeEnv->resultRowInfo, 0); - copyAndFillResult(pQInfo); + pOperator->name = "TimeIntervalAggOperator"; + pOperator->operatorType = OP_TimeInterval; + pOperator->blockingOptr = true; + pOperator->status = OP_IN_EXECUTING; + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; + pOperator->exec = doIntervalAgg; + pOperator->cleanup = destroyBasicOperatorInfo; + + return pOperator; +} + +SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { + STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo)); + + pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset); + pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); + initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT); + + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "MultiTableTimeIntervalOperator"; + pOperator->operatorType = OP_MultiTableTimeInterval; + pOperator->blockingOptr = true; + pOperator->status = OP_IN_EXECUTING; + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; + + pOperator->exec = doSTableIntervalAgg; + pOperator->cleanup = destroyBasicOperatorInfo; + + return pOperator; +} + +SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { + SGroupbyOperatorInfo* pInfo = calloc(1, sizeof(SGroupbyOperatorInfo)); + pInfo->colIndex = -1; // group by column index + + pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); + pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); + initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT); + + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "GroupbyAggOperator"; + pOperator->blockingOptr = true; + pOperator->status = OP_IN_EXECUTING; + pOperator->operatorType = OP_Groupby; + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; + pOperator->exec = hashGroupbyAggregate; + pOperator->cleanup = destroyGroupbyOperatorInfo; + + return pOperator; +} + +SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, + int32_t numOfOutput) { + SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo)); + pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); + + { + SQuery* pQuery = pRuntimeEnv->pQuery; + SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfOutput, pQuery->fillVal); + STimeWindow w = TSWINDOW_INITIALIZER; + + TSKEY sk = MIN(pQuery->window.skey, pQuery->window.ekey); + TSKEY ek = MAX(pQuery->window.skey, pQuery->window.ekey); + getAlignQueryTimeWindow(pQuery, pQuery->window.skey, sk, ek, &w); + + pInfo->pFillInfo = taosCreateFillInfo(pQuery->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput, + pQuery->interval.sliding, pQuery->interval.slidingUnit, (int8_t)pQuery->precision, + pQuery->fillType, pColInfo, pRuntimeEnv->qinfo); } + + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + + pOperator->name = "FillOperator"; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->operatorType = OP_Fill; + + pOperator->upstream = upstream; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->info = pInfo; + pOperator->pRuntimeEnv = pRuntimeEnv; + + pOperator->exec = doFill; + pOperator->cleanup = destroySFillOperatorInfo; + + return pOperator; } -void tableQueryImpl(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; +static SSDataBlock* doTagScan(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } + + SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; + + int32_t maxNumOfTables = (int32_t)pRuntimeEnv->resultInfo.capacity; + + STagScanInfo *pInfo = pOperator->info; + SSDataBlock *pRes = pInfo->pRes; + + int32_t count = 0; + SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0); + + int32_t functionId = pOperator->pExpr[0].base.functionId; + if (functionId == TSDB_FUNC_TID_TAG) { // return the tags & table Id + SQuery* pQuery = pRuntimeEnv->pQuery; + assert(pQuery->numOfOutput == 1); + + SExprInfo* pExprInfo = &pOperator->pExpr[0]; + int32_t rsize = pExprInfo->bytes; + + count = 0; + + int16_t bytes = pExprInfo->bytes; + int16_t type = pExprInfo->type; + + for(int32_t i = 0; i < pQuery->numOfTags; ++i) { + if (pQuery->tagColList[i].colId == pExprInfo->base.colInfo.colId) { + bytes = pQuery->tagColList[i].bytes; + type = pQuery->tagColList[i].type; + break; + } + } + + SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0); + + while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) { + int32_t i = pInfo->currentIndex++; + STableQueryInfo *item = taosArrayGetP(pa, i); + + char *output = pColInfo->pData + count * rsize; + varDataSetLen(output, rsize - VARSTR_HEADER_SIZE); + + output = varDataVal(output); + STableId* id = TSDB_TABLEID(item->pTable); + + *(int16_t *)output = 0; + output += sizeof(int16_t); - if (hasNotReturnedResults(pRuntimeEnv, &pQInfo->groupResInfo)) { - if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) { - /* - * There are remain results that are not returned due to result interpolation - * So, we do keep in this procedure instead of launching retrieve procedure for next results. - */ - pQuery->rec.rows = doFillGapsInResults(pRuntimeEnv, (tFilePage **)pQuery->sdata); - if (pQuery->rec.rows > 0) { - limitOperator(pQuery, pQInfo); - qDebug("QInfo:%p current:%" PRId64 " returned, total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total); - } else { - copyAndFillResult(pQInfo); - } + *(int64_t *)output = id->uid; // memory align problem, todo serialize + output += sizeof(id->uid); - } else { - pQuery->rec.rows = 0; - assert(pRuntimeEnv->resultRowInfo.size > 0); - copyToOutputBuf(pQInfo, &pRuntimeEnv->resultRowInfo); - doSecondaryArithmeticProcess(pQuery); + *(int32_t *)output = id->tid; + output += sizeof(id->tid); - if (pQuery->rec.rows > 0) { - limitOperator(pQuery, pQInfo); - } + *(int32_t *)output = pQuery->vgId; + output += sizeof(pQuery->vgId); - if (pQuery->rec.rows > 0) { - qDebug("QInfo:%p %" PRId64 " rows returned from group results, total:%" PRId64 "", pQInfo, pQuery->rec.rows, - pQuery->rec.total); + char* data = NULL; + if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { + data = tsdbGetTableName(item->pTable); } else { - qDebug("QInfo:%p query over, %" PRId64 " rows are returned", pQInfo, pQuery->rec.total); + data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes); } - } - return; - } + doSetTagValueToResultBuf(output, data, type, bytes); + count += 1; + } - // number of points returned during this query - pQuery->rec.rows = 0; - int64_t st = taosGetTimestampUs(); + qDebug("QInfo:%p create (tableId, tag) info completed, rows:%d", pRuntimeEnv->qinfo, count); + } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query + SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0); + *(int64_t*)pColInfo->pData = pInfo->totalTables; + count = 1; - assert(pQInfo->tableqinfoGroupInfo.numOfTables == 1); - SArray* g = GET_TABLEGROUP(pQInfo, 0); + pOperator->status = OP_EXEC_DONE; + qDebug("QInfo:%p create count(tbname) query, res:%d rows:1", pRuntimeEnv->qinfo, count); + } else { // return only the tags|table name etc. + SExprInfo* pExprInfo = pOperator->pExpr; // todo use the column list instead of exprinfo - STableQueryInfo* item = taosArrayGetP(g, 0); - pQuery->current = item; + count = 0; + while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) { + int32_t i = pInfo->currentIndex++; - // group by normal column, sliding window query, interval query are handled by interval query processor - if (QUERY_IS_INTERVAL_QUERY(pQuery) || pRuntimeEnv->groupbyColumn) { // interval (down sampling operation) - tableIntervalProcess(pQInfo, item); - } else if (isFixedOutputQuery(pRuntimeEnv)) { - tableAggregationProcess(pQInfo, item); - } else { // diff/add/multiply/subtract/division - assert(pQuery->checkResultBuf == 1); - tableProjectionProcess(pQInfo, item); - } + STableQueryInfo* item = taosArrayGetP(pa, i); - // record the total elapsed time - pRuntimeEnv->summary.elapsedTime += (taosGetTimestampUs() - st); - assert(pQInfo->tableqinfoGroupInfo.numOfTables == 1); -} + char *data = NULL, *dst = NULL; + int16_t type = 0, bytes = 0; + for(int32_t j = 0; j < pOperator->numOfOutput; ++j) { + // not assign value in case of user defined constant output column + if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) { + continue; + } -void buildTableBlockDistResult(SQInfo *pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery *pQuery = pRuntimeEnv->pQuery; - pQuery->pos = 0; + SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j); + type = pExprInfo[j].type; + bytes = pExprInfo[j].bytes; - STableBlockDist *pTableBlockDist = calloc(1, sizeof(STableBlockDist)); - pTableBlockDist->dataBlockInfos = taosArrayInit(512, sizeof(SDataBlockInfo)); - pTableBlockDist->result = (char *)malloc(512); + if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { + data = tsdbGetTableName(item->pTable); + } else { + data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes); + } - TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle; - SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; - SSchema blockDistSchema = tGetBlockDistColumnSchema(); + dst = pColInfo->pData + count * pExprInfo[j].bytes; + doSetTagValueToResultBuf(dst, data, type, bytes); + } - int64_t startTime = taosGetTimestampUs(); - while (tsdbNextDataBlockWithoutMerge(pQueryHandle)) { - if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) { - freeTableBlockDist(pTableBlockDist); - longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); + count += 1; } - if (pTableBlockDist->firstSeekTimeUs == 0) { - pTableBlockDist->firstSeekTimeUs = taosGetTimestampUs() - startTime; - } - - tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo); - taosArrayPush(pTableBlockDist->dataBlockInfos, &blockInfo); - } - if (terrno != TSDB_CODE_SUCCESS) { - freeTableBlockDist(pTableBlockDist); - longjmp(pRuntimeEnv->env, terrno); - } - pTableBlockDist->numOfRowsInMemTable = tsdbGetNumOfRowsInMemTable(pQueryHandle); - - generateBlockDistResult(pTableBlockDist); - - int type = -1; - assert(pQuery->numOfOutput == 1); - SExprInfo* pExprInfo = pQuery->pExpr1; - for (int32_t j = 0; j < pQuery->numOfOutput; j++) { - if (pExprInfo[j].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) { - type = blockDistSchema.type; + if (pInfo->currentIndex >= pInfo->totalTables) { + pOperator->status = OP_EXEC_DONE; } - assert(type == TSDB_DATA_TYPE_BINARY); - STR_WITH_SIZE_TO_VARSTR(pQuery->sdata[j]->data, pTableBlockDist->result, (VarDataLenT)strlen(pTableBlockDist->result)); - } - freeTableBlockDist(pTableBlockDist); + qDebug("QInfo:%p create tag values results completed, rows:%d", pRuntimeEnv->qinfo, count); + } - pQuery->rec.rows = 1; - setQueryStatus(pQuery, QUERY_COMPLETED); - return; + pRes->info.rows = count; + return (pRes->info.rows == 0)? NULL:pInfo->pRes; } -void stableQueryImpl(SQInfo *pQInfo) { - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery *pQuery = pRuntimeEnv->pQuery; - pQuery->rec.rows = 0; +SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput) { + STagScanInfo* pInfo = calloc(1, sizeof(STagScanInfo)); + pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); - int64_t st = taosGetTimestampUs(); + size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv); + assert(numOfGroup == 0 || numOfGroup == 1); - if (QUERY_IS_INTERVAL_QUERY(pQuery) || - (isFixedOutputQuery(pRuntimeEnv) && (!isPointInterpoQuery(pQuery)) && (!pRuntimeEnv->groupbyColumn))) { - multiTableQueryProcess(pQInfo); - } else { - assert(pQuery->checkResultBuf == 1 || isPointInterpoQuery(pQuery) || pRuntimeEnv->groupbyColumn); - sequentialTableProcess(pQInfo); - } + pInfo->totalTables = pRuntimeEnv->tableqinfoGroupInfo.numOfTables; + pInfo->currentIndex = 0; - // record the total elapsed time - pQInfo->runtimeEnv.summary.elapsedTime += (taosGetTimestampUs() - st); + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + pOperator->name = "SeqTableTagScan"; + pOperator->operatorType = OP_TagScan; + pOperator->blockingOptr = false; + pOperator->status = OP_IN_EXECUTING; + pOperator->info = pInfo; + pOperator->exec = doTagScan; + pOperator->pExpr = pExpr; + pOperator->numOfOutput = numOfOutput; + pOperator->pRuntimeEnv = pRuntimeEnv; + pOperator->cleanup = destroyTagScanOperatorInfo; + + return pOperator; } static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) { @@ -5962,7 +5234,8 @@ static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pEx if ((pFuncMsg->functionId == TSDB_FUNC_TAGPRJ) || (pFuncMsg->functionId == TSDB_FUNC_TID_TAG && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) || - (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX)) { + (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) || + (pFuncMsg->functionId == TSDB_FUNC_BLKINFO)) { continue; } @@ -6116,6 +5389,9 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex); pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId); pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); + pExprMsg->colType = htons(pExprMsg->colType); + pExprMsg->colBytes = htons(pExprMsg->colBytes); + pExprMsg->functionId = htons(pExprMsg->functionId); pExprMsg->numOfParams = htons(pExprMsg->numOfParams); pExprMsg->resColId = htons(pExprMsg->resColId); @@ -6154,7 +5430,10 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex); pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId); - pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); + pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); + pExprMsg->colType = htons(pExprMsg->colType); + pExprMsg->colBytes = htons(pExprMsg->colBytes); + pExprMsg->functionId = htons(pExprMsg->functionId); pExprMsg->numOfParams = htons(pExprMsg->numOfParams); @@ -6324,8 +5603,29 @@ static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTable return TSDB_CODE_SUCCESS; } -int32_t createQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, SSqlFuncMsg **pExprMsg, - SColumnInfo* pTagCols) { +static int32_t updateOutputBufForTopBotQuery(SQueryTableMsg* pQueryMsg, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) { + for (int32_t i = 0; i < numOfOutput; ++i) { + int16_t functId = pExprs[i].base.functionId; + + if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) { + int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols); + if (j < 0 || j >= pQueryMsg->numOfCols) { + return TSDB_CODE_QRY_INVALID_MSG; + } else { + SColumnInfo* pCol = &pQueryMsg->colList[j]; + int32_t ret = getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.arg[0].argValue.i64, + &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, tagLen, superTable); + assert(ret == TSDB_CODE_SUCCESS); + } + } + } + + return TSDB_CODE_SUCCESS; +} + +// TODO tag length should be passed from client +int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo, + SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) { *pExprInfo = NULL; int32_t code = TSDB_CODE_SUCCESS; @@ -6398,6 +5698,12 @@ int32_t createQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutpu } int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64; + if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM && + (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) { + tfree(pExprs); + return TSDB_CODE_QRY_INVALID_MSG; + } + if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) { tfree(pExprs); @@ -6411,23 +5717,59 @@ int32_t createQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutpu assert(isValidDataType(pExprs[i].type)); } - // TODO refactor + // the tag length is affected by other tag columns, so this should be update. + updateOutputBufForTopBotQuery(pQueryMsg, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable); + + *pExprInfo = pExprs; + return TSDB_CODE_SUCCESS; +} + +int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, + SSqlFuncMsg **pExprMsg, SExprInfo *prevExpr) { + *pExprInfo = NULL; + int32_t code = TSDB_CODE_SUCCESS; + + SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo)); + if (pExprs == NULL) { + return TSDB_CODE_QRY_OUT_OF_MEMORY; + } + + bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType); + for (int32_t i = 0; i < numOfOutput; ++i) { pExprs[i].base = *pExprMsg[i]; - int16_t functId = pExprs[i].base.functionId; + pExprs[i].bytes = 0; - if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) { - int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols); - if (j < 0 || j >= pQueryMsg->numOfCols) { - return TSDB_CODE_QRY_INVALID_MSG; - } else { - SColumnInfo *pCol = &pQueryMsg->colList[j]; - int32_t ret = - getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.arg[0].argValue.i64, - &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, tagLen, isSuperTable); - assert(ret == TSDB_CODE_SUCCESS); + int16_t type = 0; + int16_t bytes = 0; + + // parse the arithmetic expression + if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) { + code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg); + + if (code != TSDB_CODE_SUCCESS) { + tfree(pExprs); + return code; } + + type = TSDB_DATA_TYPE_DOUBLE; + bytes = tDataTypes[type].bytes; + } else { + int32_t index = pExprs[i].base.colInfo.colIndex; + assert(prevExpr[index].base.resColId == pExprs[i].base.colInfo.colId); + + type = prevExpr[index].type; + bytes = prevExpr[index].bytes; + } + + int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64; + if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes, + &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) { + tfree(pExprs); + return TSDB_CODE_QRY_INVALID_MSG; } + + assert(isValidDataType(pExprs[i].type)); } *pExprInfo = pExprs; @@ -6537,6 +5879,9 @@ static void doUpdateExprColumnIndex(SQuery *pQuery) { assert(f < pQuery->numOfCols); } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) { // do nothing for user-defined constant value result columns + } else if (pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) { + pColIndex->colIndex = 0;// only one source column, so it must be 0; + assert(pQuery->numOfOutput == 1); } else { int32_t f = 0; for (f = 0; f < pQuery->numOfTags; ++f) { @@ -6551,27 +5896,33 @@ static void doUpdateExprColumnIndex(SQuery *pQuery) { } } -static void calResultBufSize(SQuery* pQuery) { - const int32_t RESULT_MSG_MIN_SIZE = 1024 * (1024 + 512); // bytes - const int32_t RESULT_MSG_MIN_ROWS = 8192; - const float RESULT_THRESHOLD_RATIO = 0.85f; +void setResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo) { + const int32_t DEFAULT_RESULT_MSG_SIZE = 1024 * (1024 + 512); + + // the minimum number of rows for projection query + const int32_t MIN_ROWS_FOR_PRJ_QUERY = 8192; + const int32_t DEFAULT_MIN_ROWS = 4096; + + const float THRESHOLD_RATIO = 0.85f; if (isProjQuery(pQuery)) { - int32_t numOfRes = RESULT_MSG_MIN_SIZE / pQuery->resultRowSize; - if (numOfRes < RESULT_MSG_MIN_ROWS) { - numOfRes = RESULT_MSG_MIN_ROWS; + int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQuery->resultRowSize; + if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) { + numOfRes = MIN_ROWS_FOR_PRJ_QUERY; } - pQuery->rec.capacity = numOfRes; - pQuery->rec.threshold = (int32_t)(numOfRes * RESULT_THRESHOLD_RATIO); + pResultInfo->capacity = numOfRes; } else { // in case of non-prj query, a smaller output buffer will be used. - pQuery->rec.capacity = 4096; - pQuery->rec.threshold = (int32_t)(pQuery->rec.capacity * RESULT_THRESHOLD_RATIO); + pResultInfo->capacity = DEFAULT_MIN_ROWS; } + + pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO); + pResultInfo->total = 0; } -SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr, SExprInfo *pExprs, - SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery, char* sql) { +SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs, + SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery, + char* sql) { int16_t numOfCols = pQueryMsg->numOfCols; int16_t numOfOutput = pQueryMsg->numOfOutput; @@ -6582,15 +5933,10 @@ SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr // to make sure third party won't overwrite this structure pQInfo->signature = pQInfo; - pQInfo->tableGroupInfo = *pTableGroupInfo; - - SQuery *pQuery = calloc(1, sizeof(SQuery)); - if (pQuery == NULL) { - goto _cleanup_query; - } - + SQuery* pQuery = &pQInfo->query; pQInfo->runtimeEnv.pQuery = pQuery; + pQuery->tableGroupInfo = *pTableGroupInfo; pQuery->numOfCols = numOfCols; pQuery->numOfOutput = numOfOutput; pQuery->limit.limit = pQueryMsg->limit; @@ -6637,37 +5983,11 @@ SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr } doUpdateExprColumnIndex(pQuery); - int32_t ret = createFilterInfo(pQInfo, pQuery); if (ret != TSDB_CODE_SUCCESS) { goto _cleanup; } - // prepare the result buffer - pQuery->sdata = (tFilePage **)calloc(pQuery->numOfOutput, POINTER_BYTES); - if (pQuery->sdata == NULL) { - goto _cleanup; - } - - calResultBufSize(pQuery); - - for (int32_t col = 0; col < pQuery->numOfOutput; ++col) { - // allocate additional memory for interResults that are usually larger then final results - // TODO refactor - int16_t bytes = 0; - if (pQuery->pExpr2 == NULL || col > pQuery->numOfExpr2) { - bytes = pExprs[col].bytes; - } else { - bytes = MAX(pQuery->pExpr2[col].bytes, pExprs[col].bytes); - } - - size_t size = (size_t)((pQuery->rec.capacity + 1) * bytes + pExprs[col].interBytes + sizeof(tFilePage)); - pQuery->sdata[col] = (tFilePage *)calloc(1, size); - if (pQuery->sdata[col] == NULL) { - goto _cleanup; - } - } - if (pQuery->fillType != TSDB_FILL_NONE) { pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput); if (pQuery->fillVal == NULL) { @@ -6681,7 +6001,7 @@ SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr size_t numOfGroups = 0; if (pTableGroupInfo->pGroupList != NULL) { numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList); - STableGroupInfo* pTableqinfo = &pQInfo->tableqinfoGroupInfo; + STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo; pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES); pTableqinfo->numOfTables = pTableGroupInfo->numOfTables; @@ -6693,26 +6013,24 @@ SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr goto _cleanup; } - // NOTE: pTableCheckInfo need to update the query time range and the lastKey info - pQInfo->arrTableIdInfo = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); pQInfo->dataReady = QUERY_RESULT_NOT_READY; pQInfo->rspContext = NULL; pQInfo->sql = sql; pthread_mutex_init(&pQInfo->lock, NULL); tsem_init(&pQInfo->ready, 0, 0); - pQuery->pos = -1; pQuery->window = pQueryMsg->window; changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery); - pQInfo->runtimeEnv.queryWindowIdentical = true; + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; + pQuery->queryWindowIdentical = true; bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr); STimeWindow window = pQuery->window; int32_t index = 0; for(int32_t i = 0; i < numOfGroups; ++i) { - SArray* pa = taosArrayGetP(pQInfo->tableGroupInfo.pGroupList, i); + SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i); size_t s = taosArrayGetSize(pa); SArray* p1 = taosArrayInit(s, POINTER_BYTES); @@ -6720,14 +6038,14 @@ SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr goto _cleanup; } - taosArrayPush(pQInfo->tableqinfoGroupInfo.pGroupList, &p1); + taosArrayPush(pRuntimeEnv->tableqinfoGroupInfo.pGroupList, &p1); for(int32_t j = 0; j < s; ++j) { STableKeyInfo* info = taosArrayGet(pa, j); window.skey = info->lastKey; if (info->lastKey != pQuery->window.skey) { - pQInfo->runtimeEnv.queryWindowIdentical = false; + pQInfo->query.queryWindowIdentical = false; } void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo); @@ -6740,23 +6058,22 @@ SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr taosArrayPush(p1, &item); STableId* id = TSDB_TABLEID(info->pTable); - taosHashPut(pQInfo->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES); + taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES); index += 1; } } - colIdCheck(pQuery); + colIdCheck(pQuery, pQInfo); // todo refactor - pQInfo->runtimeEnv.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX); - + pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX); + qDebug("qmsg:%p QInfo:%p created", pQueryMsg, pQInfo); return pQInfo; _cleanup_qinfo: tsdbDestroyTableGroup(pTableGroupInfo); -_cleanup_query: if (pGroupbyExpr != NULL) { taosArrayDestroy(pGroupbyExpr->columnInfo); free(pGroupbyExpr); @@ -6794,6 +6111,8 @@ bool isValidQInfo(void *param) { int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) { int32_t code = TSDB_CODE_SUCCESS; + + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; STSBuf *pTsBuf = NULL; @@ -6818,15 +6137,15 @@ int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *p (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) { qDebug("QInfo:%p no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo, pQuery->window.skey, pQuery->window.ekey, pQuery->order.order); - setQueryStatus(pQuery, QUERY_COMPLETED); - pQInfo->tableqinfoGroupInfo.numOfTables = 0; + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); + pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0; // todo free memory return TSDB_CODE_SUCCESS; } - if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { + if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) { qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo); - setQueryStatus(pQuery, QUERY_COMPLETED); + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); return TSDB_CODE_SUCCESS; } @@ -6904,18 +6223,12 @@ void freeQInfo(SQInfo *pQInfo) { qDebug("QInfo:%p start to free QInfo", pQInfo); - releaseQueryBuf(pQInfo->tableqinfoGroupInfo.numOfTables); + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; + releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables); teardownQueryRuntimeEnv(&pQInfo->runtimeEnv); SQuery *pQuery = pQInfo->runtimeEnv.pQuery; if (pQuery != NULL) { - if (pQuery->sdata != NULL) { - for (int32_t col = 0; col < pQuery->numOfOutput; ++col) { - tfree(pQuery->sdata[col]); - } - tfree(pQuery->sdata); - } - if (pQuery->fillVal != NULL) { tfree(pQuery->fillVal); } @@ -6945,20 +6258,16 @@ void freeQInfo(SQInfo *pQInfo) { taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo); tfree(pQuery->pGroupbyExpr); } - - tfree(pQuery); } - doDestroyTableQueryInfo(&pQInfo->tableqinfoGroupInfo); + doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo); tfree(pQInfo->pBuf); tfree(pQInfo->sql); - tsdbDestroyTableGroup(&pQInfo->tableGroupInfo); - taosHashCleanup(pQInfo->arrTableIdInfo); - - taosArrayDestroy(pQInfo->groupResInfo.pRows); + tsdbDestroyTableGroup(&pQuery->tableGroupInfo); + taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows); pQInfo->signature = 0; qDebug("QInfo:%p QInfo is freed", pQInfo); @@ -6966,41 +6275,20 @@ void freeQInfo(SQInfo *pQInfo) { tfree(pQInfo); } -size_t getResultSize(SQInfo *pQInfo, int64_t *numOfRows) { - SQuery *pQuery = pQInfo->runtimeEnv.pQuery; - - /* - * get the file size and set the numOfRows to be the file size, since for tsComp query, - * the returned row size is equalled to 1 - * TODO handle the case that the file is too large to send back one time - */ - if (isTsCompQuery(pQuery) && (*numOfRows) > 0) { - struct stat fStat; - FILE *f = *(FILE **)pQuery->sdata[0]->data; - if ((f != NULL) && (fstat(fileno(f), &fStat) == 0)) { - *numOfRows = fStat.st_size; - return fStat.st_size; - } else { - qError("QInfo:%p failed to get file info, file:%p, reason:%s", pQInfo, f, strerror(errno)); - return 0; - } - } else { - return (size_t)(pQuery->resultRowSize * (*numOfRows)); - } -} - int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) { // the remained number of retrieved rows, not the interpolated result + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; // load data from file to msg buffer if (isTsCompQuery(pQuery)) { - - FILE *f = *(FILE **)pQuery->sdata[0]->data; // TODO refactor + SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0); + FILE *f = *(FILE **)pColInfoData->pData; // TODO refactor // make sure file exist if (f) { off_t s = lseek(fileno(f), 0, SEEK_END); + assert(s == pRuntimeEnv->outputBuf->info.rows); qDebug("QInfo:%p ts comp data return, file:%p, size:%"PRId64, pQInfo, f, (uint64_t)s); if (fseek(f, 0, SEEK_SET) >= 0) { @@ -7015,30 +6303,30 @@ int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) { assert(0); } + // dump error info if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) { qDump(data, s); - assert(0); } fclose(f); - *(FILE **)pQuery->sdata[0]->data = NULL; } // all data returned, set query over - if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - setQueryStatus(pQuery, QUERY_OVER); + if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) { + setQueryStatus(pRuntimeEnv, QUERY_OVER); } } else { - doCopyQueryResultToMsg(pQInfo, (int32_t)pQuery->rec.rows, data); + doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data); } - pQuery->rec.total += pQuery->rec.rows; - qDebug("QInfo:%p current numOfRes rows:%" PRId64 ", total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total); + pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows; + qDebug("QInfo:%p current numOfRes rows:%d, total:%" PRId64, pQInfo, + pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total); - if (pQuery->limit.limit > 0 && pQuery->limit.limit == pQuery->rec.total) { + if (pQuery->limit.limit > 0 && pQuery->limit.limit == pRuntimeEnv->resultInfo.total) { qDebug("QInfo:%p results limitation reached, limitation:%"PRId64, pQInfo, pQuery->limit.limit); - setQueryStatus(pQuery, QUERY_OVER); + setQueryStatus(pRuntimeEnv, QUERY_OVER); } return TSDB_CODE_SUCCESS; @@ -7077,139 +6365,6 @@ static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type } } -void buildTagQueryResult(SQInfo* pQInfo) { - SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; - SQuery * pQuery = pRuntimeEnv->pQuery; - - size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pQInfo); - assert(numOfGroup == 0 || numOfGroup == 1); - - if (numOfGroup == 0) { - return; - } - - SArray* pa = GET_TABLEGROUP(pQInfo, 0); - - size_t num = taosArrayGetSize(pa); - assert(num == pQInfo->tableqinfoGroupInfo.numOfTables); - - int32_t count = 0; - int32_t functionId = pQuery->pExpr1[0].base.functionId; - if (functionId == TSDB_FUNC_TID_TAG) { // return the tags & table Id - assert(pQuery->numOfOutput == 1); - - SExprInfo* pExprInfo = &pQuery->pExpr1[0]; - int32_t rsize = pExprInfo->bytes; - count = 0; - - int16_t bytes = pExprInfo->bytes; - int16_t type = pExprInfo->type; - - for(int32_t i = 0; i < pQuery->numOfTags; ++i) { - if (pQuery->tagColList[i].colId == pExprInfo->base.colInfo.colId) { - bytes = pQuery->tagColList[i].bytes; - type = pQuery->tagColList[i].type; - break; - } - } - - while(pQInfo->tableIndex < num && count < pQuery->rec.capacity) { - int32_t i = pQInfo->tableIndex++; - STableQueryInfo *item = taosArrayGetP(pa, i); - - char *output = pQuery->sdata[0]->data + count * rsize; - varDataSetLen(output, rsize - VARSTR_HEADER_SIZE); - - output = varDataVal(output); - STableId* id = TSDB_TABLEID(item->pTable); - - *(int16_t *)output = 0; - output += sizeof(int16_t); - - *(int64_t *)output = id->uid; // memory align problem, todo serialize - output += sizeof(id->uid); - - *(int32_t *)output = id->tid; - output += sizeof(id->tid); - - *(int32_t *)output = pQInfo->vgId; - output += sizeof(pQInfo->vgId); - - if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { - char* data = tsdbGetTableName(item->pTable); - memcpy(output, data, varDataTLen(data)); - } else { - char* data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes); - doSetTagValueToResultBuf(output, data, type, bytes); - } - - count += 1; - } - - qDebug("QInfo:%p create (tableId, tag) info completed, rows:%d", pQInfo, count); - - } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query - *(int64_t*) pQuery->sdata[0]->data = num; - - count = 1; - SET_STABLE_QUERY_OVER(pQInfo); - qDebug("QInfo:%p create count(tbname) query, res:%d rows:1", pQInfo, count); - } else { // return only the tags|table name etc. - count = 0; - SSchema* tbnameSchema = tGetTbnameColumnSchema(); - - int32_t maxNumOfTables = (int32_t)pQuery->rec.capacity; - if (pQuery->limit.limit >= 0 && pQuery->limit.limit < pQuery->rec.capacity) { - maxNumOfTables = (int32_t)pQuery->limit.limit; - } - - while(pQInfo->tableIndex < num && count < maxNumOfTables) { - int32_t i = pQInfo->tableIndex++; - - // discard current result due to offset - if (pQuery->limit.offset > 0) { - pQuery->limit.offset -= 1; - continue; - } - - SExprInfo* pExprInfo = pQuery->pExpr1; - STableQueryInfo* item = taosArrayGetP(pa, i); - - char *data = NULL, *dst = NULL; - int16_t type = 0, bytes = 0; - for(int32_t j = 0; j < pQuery->numOfOutput; ++j) { - // not assign value in case of user defined constant output column - if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) { - continue; - } - - if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { - bytes = tbnameSchema->bytes; - type = tbnameSchema->type; - - data = tsdbGetTableName(item->pTable); - dst = pQuery->sdata[j]->data + count * tbnameSchema->bytes; - } else { - type = pExprInfo[j].type; - bytes = pExprInfo[j].bytes; - - data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes); - dst = pQuery->sdata[j]->data + count * pExprInfo[j].bytes; - - } - - doSetTagValueToResultBuf(dst, data, type, bytes); - } - count += 1; - } - - qDebug("QInfo:%p create tag values results completed, rows:%d", pQInfo, count); - } - - pQuery->rec.rows = count; - setQueryStatus(pQuery, QUERY_COMPLETED); -} - static int64_t getQuerySupportBufSize(size_t numOfTables) { size_t s1 = sizeof(STableQueryInfo); size_t s2 = sizeof(SHashNode); diff --git a/src/query/src/qFill.c b/src/query/src/qFill.c index bc6376b80743bcad3e1b07f903c970eeb9e5dee2..2de1029396fb779798ea7c20da939b2153ca3dd3 100644 --- a/src/query/src/qFill.c +++ b/src/query/src/qFill.c @@ -23,18 +23,19 @@ #include "qFill.h" #include "qExtbuffer.h" #include "queryLog.h" +#include "qExecutor.h" #define FILL_IS_ASC_FILL(_f) ((_f)->order == TSDB_ORDER_ASC) #define DO_INTERPOLATION(_v1, _v2, _k1, _k2, _k) ((_v1) + ((_v2) - (_v1)) * (((double)(_k)) - ((double)(_k1))) / (((double)(_k2)) - ((double)(_k1)))) -static void setTagsValue(SFillInfo* pFillInfo, tFilePage** data, int32_t genRows) { +static void setTagsValue(SFillInfo* pFillInfo, void** data, int32_t genRows) { for(int32_t j = 0; j < pFillInfo->numOfCols; ++j) { SFillColInfo* pCol = &pFillInfo->pFillCol[j]; if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) { continue; } - char* val1 = elePtrAt(data[j]->data, pCol->col.bytes, genRows); + char* val1 = elePtrAt(data[j], pCol->col.bytes, genRows); assert(pCol->tagIndex >= 0 && pCol->tagIndex < pFillInfo->numOfTags); SFillTagColInfo* pTag = &pFillInfo->pTags[pCol->tagIndex]; @@ -44,17 +45,17 @@ static void setTagsValue(SFillInfo* pFillInfo, tFilePage** data, int32_t genRows } } -static void setNullValueForRow(SFillInfo* pFillInfo, tFilePage** data, int32_t numOfCol, int32_t rowIndex) { +static void setNullValueForRow(SFillInfo* pFillInfo, void** data, int32_t numOfCol, int32_t rowIndex) { // the first are always the timestamp column, so start from the second column. for (int32_t i = 1; i < numOfCol; ++i) { SFillColInfo* pCol = &pFillInfo->pFillCol[i]; - char* output = elePtrAt(data[i]->data, pCol->col.bytes, rowIndex); + char* output = elePtrAt(data[i], pCol->col.bytes, rowIndex); setNull(output, pCol->col.type, pCol->col.bytes); } } -static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** srcData, int64_t ts, bool outOfBound) { +static void doFillOneRowResult(SFillInfo* pFillInfo, void** data, char** srcData, int64_t ts, bool outOfBound) { char* prev = pFillInfo->prevValues; char* next = pFillInfo->nextValues; @@ -63,7 +64,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr // set the primary timestamp column value int32_t index = pFillInfo->numOfCurrent; - char* val = elePtrAt(data[0]->data, TSDB_KEYSIZE, index); + char* val = elePtrAt(data[0], TSDB_KEYSIZE, index); *(TSKEY*) val = pFillInfo->currentKey; // set the other values @@ -77,7 +78,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr continue; } - char* output = elePtrAt(data[i]->data, pCol->col.bytes, index); + char* output = elePtrAt(data[i], pCol->col.bytes, index); assignVal(output, p + pCol->col.offset, pCol->col.bytes, pCol->col.type); } } else { // no prev value yet, set the value for NULL @@ -93,7 +94,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr continue; } - char* output = elePtrAt(data[i]->data, pCol->col.bytes, index); + char* output = elePtrAt(data[i], pCol->col.bytes, index); assignVal(output, p + pCol->col.offset, pCol->col.bytes, pCol->col.type); } } else { // no prev value yet, set the value for NULL @@ -111,7 +112,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr int16_t type = pCol->col.type; int16_t bytes = pCol->col.bytes; - char *val1 = elePtrAt(data[i]->data, pCol->col.bytes, index); + char *val1 = elePtrAt(data[i], pCol->col.bytes, index); if (type == TSDB_DATA_TYPE_BINARY|| type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BOOL) { setNull(val1, pCol->col.type, bytes); continue; @@ -132,7 +133,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr continue; } - char* val1 = elePtrAt(data[i]->data, pCol->col.bytes, index); + char* val1 = elePtrAt(data[i], pCol->col.bytes, index); assignVal(val1, (char*)&pCol->fillVal.i, pCol->col.bytes, pCol->col.type); } } @@ -162,7 +163,7 @@ static void copyCurrentRowIntoBuf(SFillInfo* pFillInfo, char** srcData, char* bu } } -static int32_t fillResultImpl(SFillInfo* pFillInfo, tFilePage** data, int32_t outputRows) { +static int32_t fillResultImpl(SFillInfo* pFillInfo, void** data, int32_t outputRows) { pFillInfo->numOfCurrent = 0; char** srcData = pFillInfo->pData; @@ -213,7 +214,7 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, tFilePage** data, int32_t ou continue; } - char* output = elePtrAt(data[i]->data, pCol->col.bytes, pFillInfo->numOfCurrent); + char* output = elePtrAt(data[i], pCol->col.bytes, pFillInfo->numOfCurrent); char* src = elePtrAt(srcData[i], pCol->col.bytes, pFillInfo->index); if (i == 0 || (pCol->functionId != TSDB_FUNC_COUNT && !isNull(src, pCol->col.type)) || @@ -255,7 +256,7 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, tFilePage** data, int32_t ou return pFillInfo->numOfCurrent; } -static int64_t appendFilledResult(SFillInfo* pFillInfo, tFilePage** output, int64_t resultCapacity) { +static int64_t appendFilledResult(SFillInfo* pFillInfo, void** output, int64_t resultCapacity) { /* * These data are generated according to fill strategy, since the current timestamp is out of the time window of * real result set. Note that we need to keep the direct previous result rows, to generated the filled data. @@ -278,7 +279,7 @@ static int32_t setTagColumnInfo(SFillInfo* pFillInfo, int32_t numOfCols, int32_t int32_t k = 0; for (int32_t i = 0; i < numOfCols; ++i) { SFillColInfo* pColInfo = &pFillInfo->pFillCol[i]; - pFillInfo->pData[i] = calloc(1, pColInfo->col.bytes * capacity); + pFillInfo->pData[i] = NULL; if (TSDB_COL_IS_TAG(pColInfo->flag)) { bool exists = false; @@ -356,6 +357,10 @@ SFillInfo* taosCreateFillInfo(int32_t order, TSKEY skey, int32_t numOfTags, int3 pFillInfo->rowSize = setTagColumnInfo(pFillInfo, pFillInfo->numOfCols, pFillInfo->alloc); assert(pFillInfo->rowSize > 0); + for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) { + pFillInfo->pData[i] = malloc(pFillInfo->pFillCol[i].col.bytes * pFillInfo->alloc); + } + return pFillInfo; } @@ -375,11 +380,16 @@ void* taosDestroyFillInfo(SFillInfo* pFillInfo) { tfree(pFillInfo->prevValues); tfree(pFillInfo->nextValues); - tfree(pFillInfo->pTags); - + + for(int32_t i = 0; i < pFillInfo->numOfTags; ++i) { + tfree(pFillInfo->pTags[i].tagVal); + } + for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) { tfree(pFillInfo->pData[i]); } + + tfree(pFillInfo->pTags); tfree(pFillInfo->pData); tfree(pFillInfo->pFillCol); @@ -413,10 +423,19 @@ void taosFillSetStartInfo(SFillInfo* pFillInfo, int32_t numOfRows, TSKEY endKey) } } -// copy the data into source data buffer -void taosFillSetDataBlockFromFilePage(SFillInfo* pFillInfo, const tFilePage** pInput) { +void taosFillSetInputDataBlock(SFillInfo* pFillInfo, const SSDataBlock* pInput) { for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) { - memcpy(pFillInfo->pData[i], pInput[i]->data, pFillInfo->numOfRows * pFillInfo->pFillCol[i].col.bytes); + SColumnInfoData* pColData = taosArrayGet(pInput->pDataBlock, i); +// pFillInfo->pData[i] = pColData->pData; + if (pInput->info.rows > pFillInfo->alloc) { + char* t = realloc(pFillInfo->pData[i], pColData->info.bytes * pInput->info.rows); + assert(t != NULL); + + pFillInfo->pData[i] = t; + pFillInfo->alloc = pInput->info.rows; + } + + memcpy(pFillInfo->pData[i], pColData->pData, pColData->info.bytes * pInput->info.rows); } } @@ -427,12 +446,20 @@ void taosFillCopyInputDataFromOneFilePage(SFillInfo* pFillInfo, const tFilePage* SFillColInfo* pCol = &pFillInfo->pFillCol[i]; const char* data = pInput->data + pCol->col.offset * pInput->num; - memcpy(pFillInfo->pData[i], data, (size_t)(pInput->num * pCol->col.bytes)); + if (pInput->num > pFillInfo->alloc) { + char* t = realloc(pFillInfo->pData[i], (size_t)(pCol->col.bytes * pInput->num)); + assert(t != NULL); + + pFillInfo->pData[i] = t; + pFillInfo->alloc = (int32_t)pInput->num; + } + + memcpy(pFillInfo->pData[i], data, (size_t)(pCol->col.bytes * pInput->num)); if (TSDB_COL_IS_TAG(pCol->flag)) { // copy the tag value to tag value buffer SFillTagColInfo* pTag = &pFillInfo->pTags[pCol->tagIndex]; assert (pTag->col.colId == pCol->col.colId); - memcpy(pTag->tagVal, data, pCol->col.bytes); + memcpy(pTag->tagVal, data, pCol->col.bytes); // TODO not memcpy?? } } } @@ -490,7 +517,7 @@ int32_t taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* return TSDB_CODE_SUCCESS; } -int64_t taosFillResultDataBlock(SFillInfo* pFillInfo, tFilePage** output, int32_t capacity) { +int64_t taosFillResultDataBlock(SFillInfo* pFillInfo, void** output, int32_t capacity) { int32_t remain = taosNumOfRemainRows(pFillInfo); int64_t numOfRes = getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, capacity); diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index d18eae033b3ecb4dc2b5870e979c0cba5c28d0a2..2488b563b9e58c3082321826411113cba8f17270 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -135,28 +135,33 @@ tSQLExpr *tSqlExprIdValueCreate(SStrToken *pToken, int32_t optrType) { if (optrType == TK_INTEGER || optrType == TK_STRING || optrType == TK_FLOAT || optrType == TK_BOOL) { toTSDBType(pToken->type); - tVariantCreate(&pSqlExpr->val, pToken); - pSqlExpr->nSQLOptr = optrType; + tVariantCreate(&pSqlExpr->value, pToken); + pSqlExpr->tokenId = optrType; + pSqlExpr->type = SQL_NODE_VALUE; } else if (optrType == TK_NOW) { // use microsecond by default - pSqlExpr->val.i64 = taosGetTimestamp(TSDB_TIME_PRECISION_MICRO); - pSqlExpr->val.nType = TSDB_DATA_TYPE_BIGINT; - pSqlExpr->nSQLOptr = TK_TIMESTAMP; // TK_TIMESTAMP used to denote the time value is in microsecond + pSqlExpr->value.i64 = taosGetTimestamp(TSDB_TIME_PRECISION_MICRO); + pSqlExpr->value.nType = TSDB_DATA_TYPE_BIGINT; + pSqlExpr->tokenId = TK_TIMESTAMP; // TK_TIMESTAMP used to denote the time value is in microsecond + pSqlExpr->type = SQL_NODE_VALUE; } else if (optrType == TK_VARIABLE) { - int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pSqlExpr->val.i64); + int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pSqlExpr->value.i64); if (ret != TSDB_CODE_SUCCESS) { terrno = TSDB_CODE_TSC_SQL_SYNTAX_ERROR; } - pSqlExpr->val.nType = TSDB_DATA_TYPE_BIGINT; - pSqlExpr->nSQLOptr = TK_TIMESTAMP; - } else { // it must be the column name (tk_id) if it is not the number + pSqlExpr->value.nType = TSDB_DATA_TYPE_BIGINT; + pSqlExpr->tokenId = TK_TIMESTAMP; + pSqlExpr->type = SQL_NODE_VALUE; + } else { + // Here it must be the column name (tk_id) if it is not a number or string. assert(optrType == TK_ID || optrType == TK_ALL); if (pToken != NULL) { pSqlExpr->colInfo = *pToken; } - pSqlExpr->nSQLOptr = optrType; + pSqlExpr->tokenId = optrType; + pSqlExpr->type = SQL_NODE_TABLE_COLUMN; } return pSqlExpr; @@ -167,19 +172,22 @@ tSQLExpr *tSqlExprIdValueCreate(SStrToken *pToken, int32_t optrType) { * function name is denoted by pFunctionToken */ tSQLExpr *tSqlExprCreateFunction(tSQLExprList *pList, SStrToken *pFuncToken, SStrToken *endToken, int32_t optType) { - if (pFuncToken == NULL) return NULL; + if (pFuncToken == NULL) { + return NULL; + } tSQLExpr *pExpr = calloc(1, sizeof(tSQLExpr)); - pExpr->nSQLOptr = optType; - pExpr->pParam = pList; + pExpr->tokenId = optType; + pExpr->type = SQL_NODE_SQLFUNCTION; + pExpr->pParam = pList; int32_t len = (int32_t)((endToken->z + endToken->n) - pFuncToken->z); - pExpr->operand.z = pFuncToken->z; + pExpr->operand = (*pFuncToken); - pExpr->operand.n = len; // raw field name - pExpr->operand.type = pFuncToken->type; + pExpr->token.n = len; + pExpr->token.z = pFuncToken->z; + pExpr->token.type = pFuncToken->type; - pExpr->token = pExpr->operand; return pExpr; } @@ -190,6 +198,7 @@ tSQLExpr *tSqlExprCreateFunction(tSQLExprList *pList, SStrToken *pFuncToken, SSt tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { tSQLExpr *pExpr = calloc(1, sizeof(tSQLExpr)); + pExpr->type = SQL_NODE_EXPR; if (pLeft != NULL && pRight != NULL && (optrType != TK_IN)) { char* endPos = pRight->token.z + pRight->token.n; pExpr->token.z = pLeft->token.z; @@ -203,32 +212,33 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { * if a token is noted as the TK_TIMESTAMP, the time precision is microsecond * Otherwise, the time precision is adaptive, determined by the time precision from databases. */ - if ((pLeft->nSQLOptr == TK_INTEGER && pRight->nSQLOptr == TK_INTEGER) || - (pLeft->nSQLOptr == TK_TIMESTAMP && pRight->nSQLOptr == TK_TIMESTAMP)) { - pExpr->val.nType = TSDB_DATA_TYPE_BIGINT; - pExpr->nSQLOptr = pLeft->nSQLOptr; + if ((pLeft->tokenId == TK_INTEGER && pRight->tokenId == TK_INTEGER) || + (pLeft->tokenId == TK_TIMESTAMP && pRight->tokenId == TK_TIMESTAMP)) { + pExpr->value.nType = TSDB_DATA_TYPE_BIGINT; + pExpr->tokenId = pLeft->tokenId; + pExpr->type = SQL_NODE_VALUE; switch (optrType) { case TK_PLUS: { - pExpr->val.i64 = pLeft->val.i64 + pRight->val.i64; + pExpr->value.i64 = pLeft->value.i64 + pRight->value.i64; break; } case TK_MINUS: { - pExpr->val.i64 = pLeft->val.i64 - pRight->val.i64; + pExpr->value.i64 = pLeft->value.i64 - pRight->value.i64; break; } case TK_STAR: { - pExpr->val.i64 = pLeft->val.i64 * pRight->val.i64; + pExpr->value.i64 = pLeft->value.i64 * pRight->value.i64; break; } case TK_DIVIDE: { - pExpr->nSQLOptr = TK_FLOAT; - pExpr->val.nType = TSDB_DATA_TYPE_DOUBLE; - pExpr->val.dKey = (double)pLeft->val.i64 / pRight->val.i64; + pExpr->tokenId = TK_FLOAT; + pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE; + pExpr->value.dKey = (double)pLeft->value.i64 / pRight->value.i64; break; } case TK_REM: { - pExpr->val.i64 = pLeft->val.i64 % pRight->val.i64; + pExpr->value.i64 = pLeft->value.i64 % pRight->value.i64; break; } } @@ -236,33 +246,35 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { tSqlExprDestroy(pLeft); tSqlExprDestroy(pRight); - } else if ((pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_INTEGER) || (pLeft->nSQLOptr == TK_INTEGER && pRight->nSQLOptr == TK_FLOAT) || - (pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_FLOAT)) { - pExpr->val.nType = TSDB_DATA_TYPE_DOUBLE; - pExpr->nSQLOptr = TK_FLOAT; + } else if ((pLeft->tokenId == TK_FLOAT && pRight->tokenId == TK_INTEGER) || + (pLeft->tokenId == TK_INTEGER && pRight->tokenId == TK_FLOAT) || + (pLeft->tokenId == TK_FLOAT && pRight->tokenId == TK_FLOAT)) { + pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE; + pExpr->tokenId = TK_FLOAT; + pExpr->type = SQL_NODE_VALUE; - double left = (pLeft->val.nType == TSDB_DATA_TYPE_DOUBLE) ? pLeft->val.dKey : pLeft->val.i64; - double right = (pRight->val.nType == TSDB_DATA_TYPE_DOUBLE) ? pRight->val.dKey : pRight->val.i64; + double left = (pLeft->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pLeft->value.dKey : pLeft->value.i64; + double right = (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pRight->value.dKey : pRight->value.i64; switch (optrType) { case TK_PLUS: { - pExpr->val.dKey = left + right; + pExpr->value.dKey = left + right; break; } case TK_MINUS: { - pExpr->val.dKey = left - right; + pExpr->value.dKey = left - right; break; } case TK_STAR: { - pExpr->val.dKey = left * right; + pExpr->value.dKey = left * right; break; } case TK_DIVIDE: { - pExpr->val.dKey = left / right; + pExpr->value.dKey = left / right; break; } case TK_REM: { - pExpr->val.dKey = left - ((int64_t)(left / right)) * right; + pExpr->value.dKey = left - ((int64_t)(left / right)) * right; break; } } @@ -271,21 +283,21 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { tSqlExprDestroy(pRight); } else { - pExpr->nSQLOptr = optrType; + pExpr->tokenId = optrType; pExpr->pLeft = pLeft; pExpr->pRight = pRight; } } else if (optrType == TK_IN) { - pExpr->nSQLOptr = optrType; + pExpr->tokenId = optrType; pExpr->pLeft = pLeft; tSQLExpr *pRSub = calloc(1, sizeof(tSQLExpr)); - pRSub->nSQLOptr = TK_SET; // TODO refactor ..... + pRSub->tokenId = TK_SET; // TODO refactor ..... pRSub->pParam = (tSQLExprList *)pRight; pExpr->pRight = pRSub; } else { - pExpr->nSQLOptr = optrType; + pExpr->tokenId = optrType; pExpr->pLeft = pLeft; if (pLeft != NULL && pRight == NULL) { @@ -325,8 +337,8 @@ void tSqlExprNodeDestroy(tSQLExpr *pExpr) { return; } - if (pExpr->nSQLOptr == TK_STRING) { - tVariantDestroy(&pExpr->val); + if (pExpr->tokenId == TK_STRING) { + tVariantDestroy(&pExpr->value); } tSqlExprListDestroy(pExpr->pParam); diff --git a/src/query/src/qPercentile.c b/src/query/src/qPercentile.c index 523fa42547e34e9f0bb9ac23868ab3dc67eeec34..d36664617244cb0059b4e291da88260fac9db225 100644 --- a/src/query/src/qPercentile.c +++ b/src/query/src/qPercentile.c @@ -254,7 +254,7 @@ tMemBucket *tMemBucketCreate(int16_t nElemSize, int16_t dataType, double minval, resetSlotInfo(pBucket); - int32_t ret = createDiskbasedResultBuffer(&pBucket->pBuffer, pBucket->bytes, pBucket->bufPageSize, pBucket->bufPageSize * 512, NULL); + int32_t ret = createDiskbasedResultBuffer(&pBucket->pBuffer, pBucket->bufPageSize, pBucket->bufPageSize * 512, NULL); if (ret != TSDB_CODE_SUCCESS) { tMemBucketDestroy(pBucket); return NULL; diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index d45e76c2fd07f37afa0ffad0f9db65d5e1948c43..ed7f8c67194269b20e21809ff0948662f4f25147 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -9,8 +9,7 @@ #define GET_DATA_PAYLOAD(_p) ((char *)(_p)->pData + POINTER_BYTES) #define NO_IN_MEM_AVAILABLE_PAGES(_b) (listNEles((_b)->lruList) >= (_b)->inMemPages) -int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t rowSize, int32_t pagesize, - int32_t inMemBufSize, const void* handle) { +int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t pagesize, int32_t inMemBufSize, const void* handle) { *pResultBuf = calloc(1, sizeof(SDiskbasedResultBuf)); SDiskbasedResultBuf* pResBuf = *pResultBuf; @@ -31,7 +30,6 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t ro // at least more than 2 pages must be in memory assert(inMemBufSize >= pagesize * 2); - pResBuf->numOfRowsPerPage = (pagesize - sizeof(tFilePage)) / rowSize; pResBuf->lruList = tdListNew(POINTER_BYTES); // init id hash table @@ -387,8 +385,6 @@ void releaseResBufPageInfo(SDiskbasedResultBuf* pResultBuf, SPageInfo* pi) { pResultBuf->statis.releasePages += 1; } -size_t getNumOfRowsPerPage(const SDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; } - size_t getNumOfResultBufGroupId(const SDiskbasedResultBuf* pResultBuf) { return taosHashGetSize(pResultBuf->groupSet); } size_t getResBufSize(const SDiskbasedResultBuf* pResultBuf) { return (size_t)pResultBuf->totalBufSize; } diff --git a/src/query/src/qTokenizer.c b/src/query/src/qTokenizer.c index cb411be518e7a40306e9dfbc62b93a949609d279..d6f9671d128df5620100c54b29cbecef616b1a02 100644 --- a/src/query/src/qTokenizer.c +++ b/src/query/src/qTokenizer.c @@ -200,25 +200,6 @@ static SKeyword keywordTable[] = { {"TRIGGER", TK_TRIGGER}, {"VIEW", TK_VIEW}, {"ALL", TK_ALL}, - {"COUNT", TK_COUNT}, - {"SUM", TK_SUM}, - {"AVG", TK_AVG}, - {"MIN", TK_MIN}, - {"MAX", TK_MAX}, - {"FIRST", TK_FIRST}, - {"LAST", TK_LAST}, - {"TOP", TK_TOP}, - {"BOTTOM", TK_BOTTOM}, - {"STDDEV", TK_STDDEV}, - {"PERCENTILE", TK_PERCENTILE}, - {"APERCENTILE", TK_APERCENTILE}, - {"LEASTSQUARES", TK_LEASTSQUARES}, - {"HISTOGRAM", TK_HISTOGRAM}, - {"DIFF", TK_DIFF}, - {"SPREAD", TK_SPREAD}, - {"TWA", TK_TWA}, - {"INTERP", TK_INTERP}, - {"LAST_ROW", TK_LAST_ROW}, {"SEMI", TK_SEMI}, {"NONE", TK_NONE}, {"PREV", TK_PREV}, @@ -228,17 +209,10 @@ static SKeyword keywordTable[] = { {"TBNAME", TK_TBNAME}, {"JOIN", TK_JOIN}, {"METRICS", TK_METRICS}, - {"TBID", TK_TBID}, {"STABLE", TK_STABLE}, {"FILE", TK_FILE}, {"VNODES", TK_VNODES}, {"UNION", TK_UNION}, - {"RATE", TK_RATE}, - {"IRATE", TK_IRATE}, - {"SUM_RATE", TK_SUM_RATE}, - {"SUM_IRATE", TK_SUM_IRATE}, - {"AVG_RATE", TK_AVG_RATE}, - {"AVG_IRATE", TK_AVG_IRATE}, {"CACHELAST", TK_CACHELAST}, {"DISTINCT", TK_DISTINCT}, {"PARTITIONS", TK_PARTITIONS}, @@ -297,7 +271,7 @@ int tSQLKeywordCode(const char* z, int n) { * Return the length of the token that begins at z[0]. * Store the token type in *type before returning. */ -uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { +uint32_t tSQLGetToken(char* z, uint32_t* tokenId) { uint32_t i; switch (*z) { case ' ': @@ -307,121 +281,121 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { case '\r': { for (i = 1; isspace(z[i]); i++) { } - *tokenType = TK_SPACE; + *tokenId = TK_SPACE; return i; } case ':': { - *tokenType = TK_COLON; + *tokenId = TK_COLON; return 1; } case '-': { if (z[1] == '-') { for (i = 2; z[i] && z[i] != '\n'; i++) { } - *tokenType = TK_COMMENT; + *tokenId = TK_COMMENT; return i; } - *tokenType = TK_MINUS; + *tokenId = TK_MINUS; return 1; } case '(': { - *tokenType = TK_LP; + *tokenId = TK_LP; return 1; } case ')': { - *tokenType = TK_RP; + *tokenId = TK_RP; return 1; } case ';': { - *tokenType = TK_SEMI; + *tokenId = TK_SEMI; return 1; } case '+': { - *tokenType = TK_PLUS; + *tokenId = TK_PLUS; return 1; } case '*': { - *tokenType = TK_STAR; + *tokenId = TK_STAR; return 1; } case '/': { if (z[1] != '*' || z[2] == 0) { - *tokenType = TK_SLASH; + *tokenId = TK_SLASH; return 1; } for (i = 3; z[i] && (z[i] != '/' || z[i - 1] != '*'); i++) { } if (z[i]) i++; - *tokenType = TK_COMMENT; + *tokenId = TK_COMMENT; return i; } case '%': { - *tokenType = TK_REM; + *tokenId = TK_REM; return 1; } case '=': { - *tokenType = TK_EQ; + *tokenId = TK_EQ; return 1 + (z[1] == '='); } case '<': { if (z[1] == '=') { - *tokenType = TK_LE; + *tokenId = TK_LE; return 2; } else if (z[1] == '>') { - *tokenType = TK_NE; + *tokenId = TK_NE; return 2; } else if (z[1] == '<') { - *tokenType = TK_LSHIFT; + *tokenId = TK_LSHIFT; return 2; } else { - *tokenType = TK_LT; + *tokenId = TK_LT; return 1; } } case '>': { if (z[1] == '=') { - *tokenType = TK_GE; + *tokenId = TK_GE; return 2; } else if (z[1] == '>') { - *tokenType = TK_RSHIFT; + *tokenId = TK_RSHIFT; return 2; } else { - *tokenType = TK_GT; + *tokenId = TK_GT; return 1; } } case '!': { if (z[1] != '=') { - *tokenType = TK_ILLEGAL; + *tokenId = TK_ILLEGAL; return 2; } else { - *tokenType = TK_NE; + *tokenId = TK_NE; return 2; } } case '|': { if (z[1] != '|') { - *tokenType = TK_BITOR; + *tokenId = TK_BITOR; return 1; } else { - *tokenType = TK_CONCAT; + *tokenId = TK_CONCAT; return 2; } } case ',': { - *tokenType = TK_COMMA; + *tokenId = TK_COMMA; return 1; } case '&': { - *tokenType = TK_BITAND; + *tokenId = TK_BITAND; return 1; } case '~': { - *tokenType = TK_BITNOT; + *tokenId = TK_BITNOT; return 1; } case '?': { - *tokenType = TK_QUESTION; + *tokenId = TK_QUESTION; return 1; } case '\'': @@ -447,7 +421,7 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { if (z[i]) i++; if (strEnd) { - *tokenType = TK_STRING; + *tokenId = TK_STRING; return i; } @@ -471,10 +445,10 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { } } - *tokenType = TK_FLOAT; + *tokenId = TK_FLOAT; return i; } else { - *tokenType = TK_DOT; + *tokenId = TK_DOT; return 1; } } @@ -483,7 +457,7 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { char next = z[1]; if (next == 'b') { // bin number - *tokenType = TK_BIN; + *tokenId = TK_BIN; for (i = 2; (z[i] == '0' || z[i] == '1'); ++i) { } @@ -493,7 +467,7 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { return i; } else if (next == 'x') { //hex number - *tokenType = TK_HEX; + *tokenId = TK_HEX; for (i = 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) { } @@ -513,7 +487,7 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { case '7': case '8': case '9': { - *tokenType = TK_INTEGER; + *tokenId = TK_INTEGER; for (i = 1; isdigit(z[i]); i++) { } @@ -523,7 +497,7 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { z[i] == 'U' || z[i] == 'A' || z[i] == 'S' || z[i] == 'M' || z[i] == 'H' || z[i] == 'D' || z[i] == 'N' || z[i] == 'Y' || z[i] == 'W') && (isIdChar[(uint8_t)z[i + 1]] == 0)) { - *tokenType = TK_VARIABLE; + *tokenId = TK_VARIABLE; i += 1; return i; } @@ -534,12 +508,12 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { while (isdigit(z[i])) { i++; } - *tokenType = TK_FLOAT; + *tokenId = TK_FLOAT; seg++; } if (seg == 4) { // ip address - *tokenType = TK_IPTOKEN; + *tokenId = TK_IPTOKEN; return i; } @@ -549,14 +523,14 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { while (isdigit(z[i])) { i++; } - *tokenType = TK_FLOAT; + *tokenId = TK_FLOAT; } return i; } case '[': { for (i = 1; z[i] && z[i - 1] != ']'; i++) { } - *tokenType = TK_ID; + *tokenId = TK_ID; return i; } case 'T': @@ -567,7 +541,7 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { } if ((i == 4 && strncasecmp(z, "true", 4) == 0) || (i == 5 && strncasecmp(z, "false", 5) == 0)) { - *tokenType = TK_BOOL; + *tokenId = TK_BOOL; return i; } } @@ -577,12 +551,12 @@ uint32_t tSQLGetToken(char* z, uint32_t* tokenType) { } for (i = 1; ((z[i] & 0x80) == 0) && isIdChar[(uint8_t) z[i]]; i++) { } - *tokenType = tSQLKeywordCode(z, i); + *tokenId = tSQLKeywordCode(z, i); return i; } } - *tokenType = TK_ILLEGAL; + *tokenId = TK_ILLEGAL; return 0; } diff --git a/src/query/src/qUtil.c b/src/query/src/qUtil.c index b7a7fd28e9dc2f013457e22446ff7bc41d3fef6c..6271fab7a86a80182d9f469d95c1026b8788122d 100644 --- a/src/query/src/qUtil.c +++ b/src/query/src/qUtil.c @@ -22,6 +22,7 @@ #include "tbuffer.h" #include "tlosertree.h" #include "queryLog.h" +#include "tscompression.h" typedef struct SCompSupporter { STableQueryInfo **pTableQueryInfo; @@ -135,20 +136,22 @@ void clearResultRow(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResultRow, int16 if (pResultRow->pageId >= 0) { tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResultRow->pageId); + int16_t offset = 0; for (int32_t i = 0; i < pRuntimeEnv->pQuery->numOfOutput; ++i) { SResultRowCellInfo *pResultInfo = &pResultRow->pCellInfo[i]; - char * s = getPosInResultPage(pRuntimeEnv, i, pResultRow, page); - size_t size = pRuntimeEnv->pQuery->pExpr1[i].bytes; + int16_t size = pRuntimeEnv->pQuery->pExpr1[i].bytes; + char * s = getPosInResultPage(pRuntimeEnv->pQuery, page, pResultRow->offset, offset); memset(s, 0, size); + offset += size; RESET_RESULT_INFO(pResultInfo); } } pResultRow->numOfRows = 0; pResultRow->pageId = -1; - pResultRow->rowId = -1; + pResultRow->offset = -1; pResultRow->closed = false; if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { @@ -158,13 +161,15 @@ void clearResultRow(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResultRow, int16 } } -SResultRowCellInfo* getResultCell(SQueryRuntimeEnv* pRuntimeEnv, const SResultRow* pRow, int32_t index) { - assert(index >= 0 && index < pRuntimeEnv->pQuery->numOfOutput); - return (SResultRowCellInfo*)((char*) pRow->pCellInfo + pRuntimeEnv->rowCellInfoOffset[index]); +// TODO refactor: use macro +SResultRowCellInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_t* offset) { + assert(index >= 0 && offset != NULL); + return (SResultRowCellInfo*)((char*) pRow->pCellInfo + offset[index]); } size_t getResultRowSize(SQueryRuntimeEnv* pRuntimeEnv) { - return (pRuntimeEnv->pQuery->numOfOutput * sizeof(SResultRowCellInfo)) + pRuntimeEnv->interBufSize + sizeof(SResultRow); + SQuery* pQuery = pRuntimeEnv->pQuery; + return (pQuery->numOfOutput * sizeof(SResultRowCellInfo)) + pQuery->interBufSize + sizeof(SResultRow); } SResultRowPool* initResultRowPool(size_t size) { @@ -340,18 +345,18 @@ void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo) { pGroupResInfo->index = 0; } -void initGroupResInfo(SGroupResInfo* pGroupResInfo, SResultRowInfo* pResultInfo, int32_t offset) { +void initGroupResInfo(SGroupResInfo* pGroupResInfo, SResultRowInfo* pResultInfo) { if (pGroupResInfo->pRows != NULL) { taosArrayDestroy(pGroupResInfo->pRows); } pGroupResInfo->pRows = taosArrayFromList(pResultInfo->pResult, pResultInfo->size, POINTER_BYTES); - pGroupResInfo->index = offset; + pGroupResInfo->index = 0; assert(pGroupResInfo->index <= getNumOfTotalRes(pGroupResInfo)); } -bool hasRemainData(SGroupResInfo* pGroupResInfo) { +bool hasRemainDataInCurrentGroup(SGroupResInfo* pGroupResInfo) { if (pGroupResInfo->pRows == NULL) { return false; } @@ -359,6 +364,14 @@ bool hasRemainData(SGroupResInfo* pGroupResInfo) { return pGroupResInfo->index < taosArrayGetSize(pGroupResInfo->pRows); } +bool hasRemainData(SGroupResInfo* pGroupResInfo) { + if (hasRemainDataInCurrentGroup(pGroupResInfo)) { + return true; + } + + return pGroupResInfo->currentGroup < pGroupResInfo->totalGroup; +} + bool incNextGroup(SGroupResInfo* pGroupResInfo) { return (++pGroupResInfo->currentGroup) < pGroupResInfo->totalGroup; } @@ -372,7 +385,7 @@ int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo) { return (int32_t) taosArrayGetSize(pGroupResInfo->pRows); } -static int64_t getNumOfResultWindowRes(SQueryRuntimeEnv* pRuntimeEnv, SResultRow *pResultRow) { +static int64_t getNumOfResultWindowRes(SQueryRuntimeEnv* pRuntimeEnv, SResultRow *pResultRow, int32_t* rowCellInfoOffset) { SQuery* pQuery = pRuntimeEnv->pQuery; for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { @@ -386,7 +399,7 @@ static int64_t getNumOfResultWindowRes(SQueryRuntimeEnv* pRuntimeEnv, SResultRow continue; } - SResultRowCellInfo *pResultInfo = getResultCell(pRuntimeEnv, pResultRow, j); + SResultRowCellInfo *pResultInfo = getResultCell(pResultRow, j, rowCellInfoOffset); assert(pResultInfo != NULL); if (pResultInfo->numOfRes > 0) { @@ -437,7 +450,8 @@ static int32_t tableResultComparFn(const void *pLeft, const void *pRight, void * } } -static int32_t mergeIntoGroupResultImpl(SQueryRuntimeEnv *pRuntimeEnv, SGroupResInfo* pGroupResInfo, SArray *pTableList, void* qinfo) { +static int32_t mergeIntoGroupResultImpl(SQueryRuntimeEnv *pRuntimeEnv, SGroupResInfo* pGroupResInfo, SArray *pTableList, + int32_t* rowCellInfoOffset) { bool ascQuery = QUERY_IS_ASC_QUERY(pRuntimeEnv->pQuery); int32_t code = TSDB_CODE_SUCCESS; @@ -455,7 +469,7 @@ static int32_t mergeIntoGroupResultImpl(SQueryRuntimeEnv *pRuntimeEnv, SGroupRes pTableQueryInfoList = malloc(POINTER_BYTES * size); if (pTableQueryInfoList == NULL || posList == NULL || pGroupResInfo->pRows == NULL || pGroupResInfo->pRows == NULL) { - qError("QInfo:%p failed alloc memory", qinfo); + qError("QInfo:%p failed alloc memory", pRuntimeEnv->qinfo); code = TSDB_CODE_QRY_OUT_OF_MEMORY; goto _end; } @@ -491,7 +505,7 @@ static int32_t mergeIntoGroupResultImpl(SQueryRuntimeEnv *pRuntimeEnv, SGroupRes SResultRowInfo *pWindowResInfo = &pTableQueryInfoList[tableIndex]->resInfo; SResultRow *pWindowRes = getResultRow(pWindowResInfo, cs.rowIndex[tableIndex]); - int64_t num = getNumOfResultWindowRes(pRuntimeEnv, pWindowRes); + int64_t num = getNumOfResultWindowRes(pRuntimeEnv, pWindowRes, rowCellInfoOffset); if (num <= 0) { cs.rowIndex[tableIndex] += 1; @@ -527,7 +541,7 @@ static int32_t mergeIntoGroupResultImpl(SQueryRuntimeEnv *pRuntimeEnv, SGroupRes int64_t endt = taosGetTimestampMs(); - qDebug("QInfo:%p result merge completed for group:%d, elapsed time:%" PRId64 " ms", qinfo, + qDebug("QInfo:%p result merge completed for group:%d, elapsed time:%" PRId64 " ms", pRuntimeEnv->qinfo, pGroupResInfo->currentGroup, endt - startt); _end: @@ -538,13 +552,13 @@ static int32_t mergeIntoGroupResultImpl(SQueryRuntimeEnv *pRuntimeEnv, SGroupRes return code; } -int32_t mergeIntoGroupResult(SGroupResInfo* pGroupResInfo, SQInfo *pQInfo) { +int32_t mergeIntoGroupResult(SGroupResInfo* pGroupResInfo, SQueryRuntimeEnv* pRuntimeEnv, int32_t* offset) { int64_t st = taosGetTimestampUs(); while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) { - SArray *group = GET_TABLEGROUP(pQInfo, pGroupResInfo->currentGroup); + SArray *group = GET_TABLEGROUP(pRuntimeEnv, pGroupResInfo->currentGroup); - int32_t ret = mergeIntoGroupResultImpl(&pQInfo->runtimeEnv, pGroupResInfo, group, pQInfo); + int32_t ret = mergeIntoGroupResultImpl(pRuntimeEnv, pGroupResInfo, group, offset); if (ret != TSDB_CODE_SUCCESS) { return ret; } @@ -554,19 +568,83 @@ int32_t mergeIntoGroupResult(SGroupResInfo* pGroupResInfo, SQInfo *pQInfo) { break; } - qDebug("QInfo:%p no result in group %d, continue", pQInfo, pGroupResInfo->currentGroup); + qDebug("QInfo:%p no result in group %d, continue", pRuntimeEnv->qinfo, pGroupResInfo->currentGroup); cleanupGroupResInfo(pGroupResInfo); incNextGroup(pGroupResInfo); } - if (pGroupResInfo->currentGroup >= pGroupResInfo->totalGroup && !hasRemainData(pGroupResInfo)) { - SET_STABLE_QUERY_OVER(pQInfo); - } - int64_t elapsedTime = taosGetTimestampUs() - st; - qDebug("QInfo:%p merge res data into group, index:%d, total group:%d, elapsed time:%" PRId64 "us", pQInfo, + qDebug("QInfo:%p merge res data into group, index:%d, total group:%d, elapsed time:%" PRId64 "us", pRuntimeEnv->qinfo, pGroupResInfo->currentGroup, pGroupResInfo->totalGroup, elapsedTime); - pQInfo->runtimeEnv.summary.firstStageMergeTime += elapsedTime; +// pQInfo->summary.firstStageMergeTime += elapsedTime; return TSDB_CODE_SUCCESS; } + +void blockDistInfoToBinary(STableBlockDist* pDist, struct SBufferWriter* bw) { + tbufWriteUint32(bw, pDist->numOfTables); + tbufWriteUint16(bw, pDist->numOfFiles); + tbufWriteUint64(bw, pDist->totalSize); + tbufWriteUint32(bw, pDist->numOfRowsInMemTable); + tbufWriteUint64(bw, taosArrayGetSize(pDist->dataBlockInfos)); + + // compress the binary string + char* p = TARRAY_GET_START(pDist->dataBlockInfos); + + // compress extra bytes + size_t x = taosArrayGetSize(pDist->dataBlockInfos) * pDist->dataBlockInfos->elemSize; + char* tmp = malloc(x + 2); + + bool comp = false; + int32_t len = tsCompressString(p, (int32_t)x, 1, tmp, (int32_t)x, ONE_STAGE_COMP, NULL, 0); + if (len == -1 || len >= x) { // compress failed, do not compress this binary data + comp = false; + len = (int32_t)x; + } else { + comp = true; + } + + tbufWriteUint8(bw, comp); + tbufWriteUint32(bw, len); + if (comp) { + tbufWriteBinary(bw, tmp, len); + } else { + tbufWriteBinary(bw, p, len); + } + tfree(tmp); +} + +void blockDistInfoFromBinary(const char* data, int32_t len, STableBlockDist* pDist) { + SBufferReader br = tbufInitReader(data, len, false); + + pDist->numOfTables = tbufReadUint32(&br); + pDist->numOfFiles = tbufReadUint16(&br); + pDist->totalSize = tbufReadUint64(&br); + pDist->numOfRowsInMemTable = tbufReadUint32(&br); + int64_t numOfBlocks = tbufReadUint64(&br); + + bool comp = tbufReadUint8(&br); + uint32_t compLen = tbufReadUint32(&br); + + size_t originalLen = (size_t) (numOfBlocks*sizeof(SFileBlockInfo)); + + char* outputBuf = NULL; + if (comp) { + outputBuf = malloc(originalLen); + + size_t actualLen = compLen; + const char* compStr = tbufReadBinary(&br, &actualLen); + + int32_t orignalLen = tsDecompressString(compStr, compLen, 1, outputBuf, + (int32_t)originalLen , ONE_STAGE_COMP, NULL, 0); + assert(orignalLen == numOfBlocks*sizeof(SFileBlockInfo)); + } else { + outputBuf = (char*) tbufReadBinary(&br, &originalLen); + } + + pDist->dataBlockInfos = taosArrayFromList(outputBuf, (uint32_t) numOfBlocks, sizeof(SFileBlockInfo)); + if (comp) { + tfree(outputBuf); + } +} + diff --git a/src/query/src/queryMain.c b/src/query/src/queryMain.c index e262a3ad385273f6e7f4b3c2cbe9c075e3d4e86d..d35d4a5ff859899a6c9521ca0918788307675317 100644 --- a/src/query/src/queryMain.c +++ b/src/query/src/queryMain.c @@ -96,7 +96,7 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi } if (param.pSecExprMsg != NULL) { - if ((code = createQueryFuncExprFromMsg(pQueryMsg, pQueryMsg->secondStageOutput, ¶m.pSecExprs, param.pSecExprMsg, param.pTagColumnInfo)) != TSDB_CODE_SUCCESS) { + if ((code = createIndirectQueryFuncExprFromMsg(pQueryMsg, pQueryMsg->secondStageOutput, ¶m.pSecExprs, param.pSecExprMsg, param.pExprs)) != TSDB_CODE_SUCCESS) { goto _over; } } @@ -144,11 +144,11 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi goto _over; } - qDebug("qmsg:%p query on %" PRIzu " tables in one group from client", pQueryMsg, tableGroupInfo.numOfTables); + qDebug("qmsg:%p query on %u tables in one group from client", pQueryMsg, tableGroupInfo.numOfTables); } int64_t el = taosGetTimestampUs() - st; - qDebug("qmsg:%p tag filter completed, numOfTables:%" PRIzu ", elapsed time:%"PRId64"us", pQueryMsg, tableGroupInfo.numOfTables, el); + qDebug("qmsg:%p tag filter completed, numOfTables:%u, elapsed time:%"PRId64"us", pQueryMsg, tableGroupInfo.numOfTables, el); } else { assert(0); } @@ -209,6 +209,7 @@ bool qTableQuery(qinfo_t qinfo) { return false; } + pQInfo->startExecTs = taosGetTimestampSec(); if (isQueryKilled(pQInfo)) { @@ -216,9 +217,10 @@ bool qTableQuery(qinfo_t qinfo) { return doBuildResCheck(pQInfo); } - if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; + if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) { qDebug("QInfo:%p no table exists for query, abort", pQInfo); - setQueryStatus(pQInfo->runtimeEnv.pQuery, QUERY_COMPLETED); + setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); return doBuildResCheck(pQInfo); } @@ -232,26 +234,16 @@ bool qTableQuery(qinfo_t qinfo) { qDebug("QInfo:%p query task is launched", pQInfo); - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - if (onlyQueryTags(pQInfo->runtimeEnv.pQuery)) { - assert(pQInfo->runtimeEnv.pQueryHandle == NULL); - buildTagQueryResult(pQInfo); - } else if (pQInfo->runtimeEnv.stableQuery) { - stableQueryImpl(pQInfo); - } else if (pQInfo->runtimeEnv.queryBlockDist){ - buildTableBlockDistResult(pQInfo); - } else { - tableQueryImpl(pQInfo); - } + pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot); - SQuery* pQuery = pRuntimeEnv->pQuery; if (isQueryKilled(pQInfo)) { qDebug("QInfo:%p query is killed", pQInfo); - } else if (pQuery->rec.rows == 0) { - qDebug("QInfo:%p over, %" PRIzu " tables queried, %"PRId64" rows are returned", pQInfo, pQInfo->tableqinfoGroupInfo.numOfTables, pQuery->rec.total); + } else if (GET_NUM_OF_RESULTS(pRuntimeEnv) == 0) { + qDebug("QInfo:%p over, %u tables queried, %"PRId64" rows are returned", pQInfo, pRuntimeEnv->tableqinfoGroupInfo.numOfTables, + pRuntimeEnv->resultInfo.total); } else { - qDebug("QInfo:%p query paused, %" PRId64 " rows returned, numOfTotal:%" PRId64 " rows", - pQInfo, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows); + qDebug("QInfo:%p query paused, %d rows returned, numOfTotal:%" PRId64 " rows", + pQInfo, GET_NUM_OF_RESULTS(pRuntimeEnv), pRuntimeEnv->resultInfo.total + GET_NUM_OF_RESULTS(pRuntimeEnv)); } return doBuildResCheck(pQInfo); @@ -279,6 +271,7 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex *buildRes = true; code = pQInfo->code; } else { + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; pthread_mutex_lock(&pQInfo->lock); @@ -286,8 +279,8 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex assert(pQInfo->rspContext == NULL); if (pQInfo->dataReady == QUERY_RESULT_READY) { *buildRes = true; - qDebug("QInfo:%p retrieve result info, rowsize:%d, rows:%" PRId64 ", code:%s", pQInfo, pQuery->resultRowSize, - pQuery->rec.rows, tstrerror(pQInfo->code)); + qDebug("QInfo:%p retrieve result info, rowsize:%d, rows:%d, code:%s", pQInfo, pQuery->resultRowSize, + GET_NUM_OF_RESULTS(pRuntimeEnv), tstrerror(pQInfo->code)); } else { *buildRes = false; qDebug("QInfo:%p retrieve req set query return result after paused", pQInfo); @@ -309,12 +302,13 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co return TSDB_CODE_QRY_INVALID_QHANDLE; } - SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; - size_t size = getResultSize(pQInfo, &pQuery->rec.rows); + SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; + int32_t s = GET_NUM_OF_RESULTS(pRuntimeEnv); + size_t size = pQuery->resultRowSize * s; size += sizeof(int32_t); - size += sizeof(STableIdInfo) * taosHashGetSize(pQInfo->arrTableIdInfo); + size += sizeof(STableIdInfo) * taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap); *contLen = (int32_t)(size + sizeof(SRetrieveTableRsp)); @@ -324,27 +318,27 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co return TSDB_CODE_QRY_OUT_OF_MEMORY; } - (*pRsp)->numOfRows = htonl((int32_t)pQuery->rec.rows); + (*pRsp)->numOfRows = htonl((int32_t)s); if (pQInfo->code == TSDB_CODE_SUCCESS) { - (*pRsp)->offset = htobe64(pQuery->limit.offset); - (*pRsp)->useconds = htobe64(pRuntimeEnv->summary.elapsedTime); + (*pRsp)->offset = htobe64(pQInfo->runtimeEnv.currentOffset); + (*pRsp)->useconds = htobe64(pQInfo->summary.elapsedTime); } else { (*pRsp)->offset = 0; - (*pRsp)->useconds = htobe64(pRuntimeEnv->summary.elapsedTime); + (*pRsp)->useconds = htobe64(pQInfo->summary.elapsedTime); } (*pRsp)->precision = htons(pQuery->precision); - if (pQuery->rec.rows > 0 && pQInfo->code == TSDB_CODE_SUCCESS) { + if (GET_NUM_OF_RESULTS(&(pQInfo->runtimeEnv)) > 0 && pQInfo->code == TSDB_CODE_SUCCESS) { doDumpQueryResult(pQInfo, (*pRsp)->data); } else { - setQueryStatus(pQuery, QUERY_OVER); + setQueryStatus(pRuntimeEnv, QUERY_OVER); } pQInfo->rspContext = NULL; pQInfo->dataReady = QUERY_RESULT_NOT_READY; - if (IS_QUERY_KILLED(pQInfo) || Q_STATUS_EQUAL(pQuery->status, QUERY_OVER)) { + if (IS_QUERY_KILLED(pQInfo) || Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_OVER)) { // here current thread hold the refcount, so it is safe to free tsdbQueryHandle. *continueExec = false; (*pRsp)->completed = 1; // notify no more result to client @@ -394,8 +388,7 @@ int32_t qQueryCompleted(qinfo_t qinfo) { return TSDB_CODE_QRY_INVALID_QHANDLE; } - SQuery* pQuery = pQInfo->runtimeEnv.pQuery; - return isQueryKilled(pQInfo) || Q_STATUS_EQUAL(pQuery->status, QUERY_OVER); + return isQueryKilled(pQInfo) || Q_STATUS_EQUAL(pQInfo->runtimeEnv.status, QUERY_OVER); } void qDestroyQueryInfo(qinfo_t qHandle) { diff --git a/src/query/src/sql.c b/src/query/src/sql.c index bed9121b0411177788193b15afd10490dc187651..a66cc709b0809c46c909bdd674312e36a76549b3 100644 --- a/src/query/src/sql.c +++ b/src/query/src/sql.c @@ -23,7 +23,6 @@ ** input grammar file: */ #include -#include /************ Begin %include sections from the grammar ************************/ #include @@ -77,10 +76,8 @@ ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument -** ParseARG_PARAM Code to pass %extra_argument as a subroutine parameter ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser -** ParseCTX_* As ParseARG_ except for %extra_context ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** YYNSTATE the combined number of states. @@ -100,46 +97,39 @@ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 287 +#define YYNOCODE 263 #define YYACTIONTYPE unsigned short int #define ParseTOKENTYPE SStrToken typedef union { int yyinit; ParseTOKENTYPE yy0; - SCreateDbInfo yy100; + SLimitVal yy18; + SCreateDbInfo yy94; int yy116; - SIntervalVal yy126; - tSQLExprList* yy178; - SArray* yy207; - int64_t yy208; - tVariant yy232; - SLimitVal yy314; - SCreateTableSQL* yy414; - SSubclauseInfo* yy441; - tSQLExpr* yy484; - SCreateAcctInfo yy505; - TAOS_FIELD yy517; - SQuerySQL* yy526; - SCreatedTableInfo yy542; + SSubclauseInfo* yy141; + tSQLExprList* yy170; + tVariant yy218; + SIntervalVal yy220; + SCreatedTableInfo yy252; + tSQLExpr* yy282; + SCreateTableSQL* yy310; + SQuerySQL* yy372; + SCreateAcctInfo yy419; + SArray* yy429; + TAOS_FIELD yy451; + int64_t yy481; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif #define ParseARG_SDECL SSqlInfo* pInfo; #define ParseARG_PDECL ,SSqlInfo* pInfo -#define ParseARG_PARAM ,pInfo -#define ParseARG_FETCH SSqlInfo* pInfo=yypParser->pInfo; -#define ParseARG_STORE yypParser->pInfo=pInfo; -#define ParseCTX_SDECL -#define ParseCTX_PDECL -#define ParseCTX_PARAM -#define ParseCTX_FETCH -#define ParseCTX_STORE +#define ParseARG_FETCH SSqlInfo* pInfo = yypParser->pInfo +#define ParseARG_STORE yypParser->pInfo = pInfo #define YYFALLBACK 1 #define YYNSTATE 306 #define YYNRULE 263 -#define YYNRULE_WITH_ACTION 263 -#define YYNTOKEN 213 +#define YYNTOKEN 187 #define YY_MAX_SHIFT 305 #define YY_MIN_SHIFTREDUCE 494 #define YY_MAX_SHIFTREDUCE 756 @@ -149,7 +139,6 @@ typedef union { #define YY_MIN_REDUCE 760 #define YY_MAX_REDUCE 1022 /************* End control #defines *******************************************/ -#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. @@ -231,149 +220,146 @@ static const YYACTIONTYPE yy_action[] = { /* 120 */ 209, 41, 24, 50, 253, 55, 53, 57, 54, 957, /* 130 */ 36, 248, 704, 46, 45, 135, 664, 44, 43, 42, /* 140 */ 47, 49, 894, 51, 52, 241, 892, 209, 41, 229, - /* 150 */ 50, 253, 55, 53, 57, 54, 233, 232, 101, 213, - /* 160 */ 46, 45, 903, 289, 44, 43, 42, 23, 267, 298, + /* 150 */ 50, 253, 55, 53, 57, 54, 233, 232, 180, 213, + /* 160 */ 46, 45, 903, 218, 44, 43, 42, 23, 267, 298, /* 170 */ 297, 266, 265, 264, 296, 263, 295, 294, 293, 262, /* 180 */ 292, 291, 866, 30, 854, 855, 856, 857, 858, 859, /* 190 */ 860, 861, 862, 863, 864, 865, 867, 868, 51, 52, /* 200 */ 917, 76, 209, 41, 900, 50, 253, 55, 53, 57, - /* 210 */ 54, 299, 18, 180, 198, 46, 45, 30, 269, 44, + /* 210 */ 54, 299, 18, 30, 198, 46, 45, 69, 269, 44, /* 220 */ 43, 42, 208, 717, 272, 269, 708, 903, 711, 185, - /* 230 */ 714, 1001, 208, 717, 69, 186, 708, 906, 711, 77, - /* 240 */ 714, 114, 113, 184, 1000, 644, 215, 221, 641, 657, - /* 250 */ 642, 71, 643, 12, 205, 206, 25, 80, 252, 145, - /* 260 */ 23, 902, 298, 297, 205, 206, 891, 296, 999, 295, + /* 230 */ 714, 219, 208, 717, 271, 186, 708, 906, 711, 101, + /* 240 */ 714, 114, 113, 184, 289, 644, 215, 221, 641, 891, + /* 250 */ 642, 128, 643, 1014, 205, 206, 77, 902, 252, 36, + /* 260 */ 23, 706, 298, 297, 205, 206, 967, 296, 71, 295, /* 270 */ 294, 293, 24, 292, 291, 874, 223, 224, 872, 873, - /* 280 */ 36, 193, 904, 875, 805, 877, 878, 876, 161, 879, - /* 290 */ 880, 55, 53, 57, 54, 67, 220, 619, 814, 46, + /* 280 */ 36, 1001, 904, 875, 805, 877, 878, 876, 161, 879, + /* 290 */ 880, 55, 53, 57, 54, 1000, 220, 707, 814, 46, /* 300 */ 45, 235, 161, 44, 43, 42, 99, 104, 192, 44, - /* 310 */ 43, 42, 93, 103, 109, 112, 102, 239, 78, 254, - /* 320 */ 218, 31, 106, 5, 151, 56, 1, 149, 194, 33, - /* 330 */ 150, 88, 83, 87, 30, 56, 169, 165, 716, 128, - /* 340 */ 30, 30, 167, 164, 117, 116, 115, 36, 716, 889, - /* 350 */ 890, 29, 893, 715, 645, 806, 46, 45, 1014, 161, - /* 360 */ 44, 43, 42, 715, 222, 685, 686, 276, 275, 302, - /* 370 */ 301, 122, 3, 162, 706, 273, 672, 710, 903, 713, - /* 380 */ 132, 277, 281, 676, 903, 903, 652, 60, 219, 677, - /* 390 */ 207, 271, 737, 20, 238, 718, 19, 61, 709, 19, - /* 400 */ 712, 64, 630, 905, 256, 632, 31, 258, 31, 60, - /* 410 */ 707, 79, 631, 178, 28, 720, 60, 259, 62, 179, - /* 420 */ 65, 92, 91, 111, 110, 14, 13, 98, 97, 16, - /* 430 */ 15, 648, 181, 649, 6, 646, 175, 647, 127, 125, - /* 440 */ 182, 183, 189, 190, 967, 188, 173, 187, 966, 177, - /* 450 */ 210, 963, 962, 211, 280, 129, 919, 927, 39, 949, - /* 460 */ 948, 934, 936, 131, 146, 899, 144, 147, 148, 36, - /* 470 */ 817, 261, 37, 171, 34, 270, 813, 237, 1019, 89, - /* 480 */ 1018, 1016, 126, 152, 274, 1013, 95, 671, 242, 1012, - /* 490 */ 200, 1010, 153, 835, 246, 35, 32, 916, 38, 172, - /* 500 */ 63, 66, 802, 136, 58, 251, 137, 138, 249, 247, - /* 510 */ 105, 800, 107, 245, 108, 243, 40, 798, 139, 797, - /* 520 */ 290, 100, 225, 282, 163, 795, 283, 794, 793, 792, - /* 530 */ 791, 790, 166, 168, 787, 785, 783, 781, 779, 284, - /* 540 */ 170, 286, 240, 72, 73, 950, 285, 287, 288, 300, - /* 550 */ 756, 195, 227, 217, 260, 228, 755, 230, 196, 191, - /* 560 */ 231, 84, 85, 754, 742, 234, 796, 238, 74, 654, - /* 570 */ 673, 118, 789, 156, 119, 155, 836, 154, 157, 158, - /* 580 */ 160, 159, 120, 788, 2, 121, 780, 4, 870, 255, - /* 590 */ 8, 901, 68, 133, 202, 244, 140, 141, 142, 143, - /* 600 */ 882, 678, 134, 26, 27, 9, 10, 719, 7, 11, - /* 610 */ 721, 21, 22, 257, 82, 583, 579, 80, 577, 576, - /* 620 */ 575, 572, 545, 268, 86, 90, 31, 94, 59, 96, + /* 310 */ 43, 42, 93, 103, 109, 112, 102, 254, 78, 302, + /* 320 */ 301, 122, 106, 5, 151, 56, 1, 149, 999, 33, + /* 330 */ 150, 88, 83, 87, 657, 56, 169, 165, 716, 30, + /* 340 */ 30, 25, 167, 164, 117, 116, 115, 30, 716, 889, + /* 350 */ 890, 29, 893, 715, 645, 193, 46, 45, 3, 162, + /* 360 */ 44, 43, 42, 715, 222, 207, 806, 276, 275, 12, + /* 370 */ 161, 685, 686, 80, 652, 145, 710, 709, 713, 712, + /* 380 */ 273, 277, 238, 903, 903, 239, 672, 61, 281, 31, + /* 390 */ 132, 903, 676, 677, 737, 718, 60, 20, 19, 19, + /* 400 */ 64, 194, 630, 256, 92, 91, 31, 31, 62, 6, + /* 410 */ 178, 632, 258, 720, 631, 60, 79, 28, 60, 65, + /* 420 */ 259, 14, 13, 67, 648, 619, 649, 179, 98, 97, + /* 430 */ 16, 15, 646, 966, 647, 111, 110, 127, 125, 181, + /* 440 */ 175, 182, 183, 189, 190, 188, 173, 187, 177, 905, + /* 450 */ 210, 963, 919, 962, 211, 280, 949, 39, 129, 948, + /* 460 */ 144, 927, 934, 36, 936, 126, 131, 146, 899, 237, + /* 470 */ 147, 671, 142, 148, 817, 261, 136, 37, 251, 66, + /* 480 */ 916, 58, 63, 137, 171, 138, 34, 270, 242, 249, + /* 490 */ 813, 1019, 89, 200, 1018, 1016, 246, 139, 247, 152, + /* 500 */ 140, 274, 1013, 95, 245, 1012, 1010, 153, 835, 35, + /* 510 */ 243, 32, 38, 172, 40, 802, 105, 800, 107, 108, + /* 520 */ 798, 797, 225, 163, 795, 794, 793, 792, 791, 790, + /* 530 */ 166, 168, 787, 785, 783, 781, 779, 170, 290, 240, + /* 540 */ 72, 73, 950, 100, 282, 283, 284, 285, 286, 287, + /* 550 */ 288, 300, 756, 195, 217, 260, 227, 228, 755, 230, + /* 560 */ 196, 191, 231, 84, 85, 754, 742, 234, 238, 654, + /* 570 */ 74, 68, 673, 255, 796, 8, 156, 133, 836, 118, + /* 580 */ 154, 159, 155, 158, 157, 160, 119, 789, 2, 120, + /* 590 */ 870, 788, 901, 121, 780, 4, 202, 141, 678, 143, + /* 600 */ 244, 134, 9, 10, 82, 719, 882, 26, 27, 7, + /* 610 */ 11, 21, 721, 22, 583, 257, 579, 577, 80, 576, + /* 620 */ 575, 572, 545, 268, 86, 90, 31, 94, 96, 59, /* 630 */ 622, 621, 618, 567, 565, 557, 563, 559, 561, 555, /* 640 */ 553, 586, 585, 584, 582, 581, 580, 578, 574, 573, /* 650 */ 60, 543, 511, 509, 760, 759, 759, 759, 759, 759, /* 660 */ 759, 759, 759, 759, 759, 759, 123, 124, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 276, 1, 276, 215, 216, 276, 216, 5, 276, 9, - /* 10 */ 286, 285, 286, 13, 14, 216, 16, 17, 216, 235, - /* 20 */ 20, 21, 276, 23, 24, 25, 26, 27, 28, 213, - /* 30 */ 214, 285, 286, 33, 34, 33, 34, 37, 38, 39, - /* 40 */ 13, 14, 235, 16, 17, 261, 216, 20, 21, 1, - /* 50 */ 23, 24, 25, 26, 27, 28, 257, 9, 37, 260, - /* 60 */ 33, 34, 235, 216, 37, 38, 39, 14, 261, 16, - /* 70 */ 17, 216, 282, 20, 21, 259, 23, 24, 25, 26, - /* 80 */ 27, 28, 280, 216, 282, 81, 33, 34, 261, 273, + /* 0 */ 251, 1, 251, 190, 191, 251, 191, 5, 251, 9, + /* 10 */ 261, 260, 261, 13, 14, 191, 16, 17, 191, 210, + /* 20 */ 20, 21, 251, 23, 24, 25, 26, 27, 28, 188, + /* 30 */ 189, 260, 261, 33, 34, 33, 34, 37, 38, 39, + /* 40 */ 13, 14, 210, 16, 17, 236, 191, 20, 21, 1, + /* 50 */ 23, 24, 25, 26, 27, 28, 232, 9, 37, 235, + /* 60 */ 33, 34, 210, 191, 37, 38, 39, 14, 236, 16, + /* 70 */ 17, 191, 257, 20, 21, 234, 23, 24, 25, 26, + /* 80 */ 27, 28, 255, 191, 257, 81, 33, 34, 236, 248, /* 90 */ 37, 38, 39, 45, 46, 47, 48, 49, 50, 51, - /* 100 */ 52, 53, 54, 55, 56, 57, 58, 277, 222, 61, - /* 110 */ 110, 1, 257, 13, 14, 260, 16, 17, 216, 9, - /* 120 */ 20, 21, 104, 23, 24, 25, 26, 27, 28, 282, - /* 130 */ 112, 284, 105, 33, 34, 216, 115, 37, 38, 39, - /* 140 */ 13, 14, 256, 16, 17, 278, 0, 20, 21, 134, - /* 150 */ 23, 24, 25, 26, 27, 28, 141, 142, 76, 257, - /* 160 */ 33, 34, 260, 81, 37, 38, 39, 88, 89, 90, + /* 100 */ 52, 53, 54, 55, 56, 57, 58, 252, 197, 61, + /* 110 */ 110, 1, 232, 13, 14, 235, 16, 17, 191, 9, + /* 120 */ 20, 21, 104, 23, 24, 25, 26, 27, 28, 257, + /* 130 */ 112, 259, 105, 33, 34, 191, 115, 37, 38, 39, + /* 140 */ 13, 14, 231, 16, 17, 253, 0, 20, 21, 134, + /* 150 */ 23, 24, 25, 26, 27, 28, 141, 142, 251, 232, + /* 160 */ 33, 34, 235, 67, 37, 38, 39, 88, 89, 90, /* 170 */ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - /* 180 */ 101, 102, 234, 216, 236, 237, 238, 239, 240, 241, - /* 190 */ 242, 243, 244, 245, 246, 247, 248, 249, 16, 17, - /* 200 */ 259, 282, 20, 21, 216, 23, 24, 25, 26, 27, - /* 210 */ 28, 235, 44, 276, 273, 33, 34, 216, 79, 37, - /* 220 */ 38, 39, 1, 2, 257, 79, 5, 260, 7, 61, - /* 230 */ 9, 276, 1, 2, 222, 67, 5, 261, 7, 262, - /* 240 */ 9, 73, 74, 75, 276, 2, 258, 216, 5, 109, - /* 250 */ 7, 274, 9, 104, 33, 34, 116, 108, 37, 110, - /* 260 */ 88, 260, 90, 91, 33, 34, 254, 95, 276, 97, - /* 270 */ 98, 99, 104, 101, 102, 234, 33, 34, 237, 238, - /* 280 */ 112, 276, 251, 242, 221, 244, 245, 246, 225, 248, - /* 290 */ 249, 25, 26, 27, 28, 104, 67, 106, 221, 33, - /* 300 */ 34, 133, 225, 37, 38, 39, 62, 63, 140, 37, - /* 310 */ 38, 39, 68, 69, 70, 71, 72, 105, 222, 15, - /* 320 */ 67, 109, 78, 62, 63, 104, 223, 224, 276, 68, - /* 330 */ 69, 70, 71, 72, 216, 104, 62, 63, 117, 104, - /* 340 */ 216, 216, 68, 69, 70, 71, 72, 112, 117, 253, - /* 350 */ 254, 255, 256, 132, 111, 221, 33, 34, 261, 225, - /* 360 */ 37, 38, 39, 132, 135, 123, 124, 138, 139, 64, - /* 370 */ 65, 66, 219, 220, 1, 257, 105, 5, 260, 7, - /* 380 */ 109, 257, 257, 105, 260, 260, 105, 109, 135, 105, - /* 390 */ 60, 138, 105, 109, 113, 105, 109, 109, 5, 109, - /* 400 */ 7, 109, 105, 261, 105, 105, 109, 105, 109, 109, - /* 410 */ 37, 109, 105, 276, 104, 111, 109, 107, 130, 276, - /* 420 */ 128, 136, 137, 76, 77, 136, 137, 136, 137, 136, - /* 430 */ 137, 5, 276, 7, 104, 5, 276, 7, 62, 63, - /* 440 */ 276, 276, 276, 276, 252, 276, 276, 276, 252, 276, - /* 450 */ 252, 252, 252, 252, 252, 216, 259, 216, 275, 283, - /* 460 */ 283, 216, 216, 216, 216, 216, 263, 216, 216, 112, - /* 470 */ 216, 216, 216, 216, 216, 216, 216, 259, 216, 216, - /* 480 */ 216, 216, 60, 216, 216, 216, 216, 117, 279, 216, - /* 490 */ 279, 216, 216, 216, 279, 216, 216, 272, 216, 216, - /* 500 */ 129, 127, 216, 271, 126, 121, 270, 269, 125, 120, - /* 510 */ 216, 216, 216, 119, 216, 118, 131, 216, 268, 216, - /* 520 */ 103, 87, 216, 86, 216, 216, 50, 216, 216, 216, - /* 530 */ 216, 216, 216, 216, 216, 216, 216, 216, 216, 83, - /* 540 */ 216, 54, 217, 217, 217, 217, 85, 84, 82, 79, - /* 550 */ 5, 217, 143, 217, 217, 5, 5, 143, 217, 217, - /* 560 */ 5, 222, 222, 5, 89, 134, 217, 113, 109, 105, - /* 570 */ 105, 218, 217, 227, 218, 231, 233, 232, 230, 228, - /* 580 */ 226, 229, 218, 217, 223, 218, 217, 219, 250, 107, - /* 590 */ 104, 259, 114, 104, 1, 104, 267, 266, 265, 264, - /* 600 */ 250, 105, 104, 109, 109, 122, 122, 105, 104, 104, - /* 610 */ 111, 104, 104, 107, 76, 9, 5, 108, 5, 5, - /* 620 */ 5, 5, 80, 15, 76, 137, 109, 137, 16, 137, + /* 180 */ 101, 102, 209, 191, 211, 212, 213, 214, 215, 216, + /* 190 */ 217, 218, 219, 220, 221, 222, 223, 224, 16, 17, + /* 200 */ 234, 257, 20, 21, 191, 23, 24, 25, 26, 27, + /* 210 */ 28, 210, 44, 191, 248, 33, 34, 197, 79, 37, + /* 220 */ 38, 39, 1, 2, 232, 79, 5, 235, 7, 61, + /* 230 */ 9, 135, 1, 2, 138, 67, 5, 236, 7, 76, + /* 240 */ 9, 73, 74, 75, 81, 2, 233, 191, 5, 229, + /* 250 */ 7, 104, 9, 236, 33, 34, 237, 235, 37, 112, + /* 260 */ 88, 1, 90, 91, 33, 34, 227, 95, 249, 97, + /* 270 */ 98, 99, 104, 101, 102, 209, 33, 34, 212, 213, + /* 280 */ 112, 251, 226, 217, 196, 219, 220, 221, 200, 223, + /* 290 */ 224, 25, 26, 27, 28, 251, 67, 37, 196, 33, + /* 300 */ 34, 133, 200, 37, 38, 39, 62, 63, 140, 37, + /* 310 */ 38, 39, 68, 69, 70, 71, 72, 15, 197, 64, + /* 320 */ 65, 66, 78, 62, 63, 104, 198, 199, 251, 68, + /* 330 */ 69, 70, 71, 72, 109, 104, 62, 63, 117, 191, + /* 340 */ 191, 116, 68, 69, 70, 71, 72, 191, 117, 228, + /* 350 */ 229, 230, 231, 132, 111, 251, 33, 34, 194, 195, + /* 360 */ 37, 38, 39, 132, 135, 60, 196, 138, 139, 104, + /* 370 */ 200, 123, 124, 108, 105, 110, 5, 5, 7, 7, + /* 380 */ 232, 232, 113, 235, 235, 105, 105, 109, 232, 109, + /* 390 */ 109, 235, 105, 105, 105, 105, 109, 109, 109, 109, + /* 400 */ 109, 251, 105, 105, 136, 137, 109, 109, 130, 104, + /* 410 */ 251, 105, 105, 111, 105, 109, 109, 104, 109, 128, + /* 420 */ 107, 136, 137, 104, 5, 106, 7, 251, 136, 137, + /* 430 */ 136, 137, 5, 227, 7, 76, 77, 62, 63, 251, + /* 440 */ 251, 251, 251, 251, 251, 251, 251, 251, 251, 236, + /* 450 */ 227, 227, 234, 227, 227, 227, 258, 250, 191, 258, + /* 460 */ 238, 191, 191, 112, 191, 60, 191, 191, 191, 234, + /* 470 */ 191, 117, 240, 191, 191, 191, 246, 191, 121, 127, + /* 480 */ 247, 126, 129, 245, 191, 244, 191, 191, 254, 125, + /* 490 */ 191, 191, 191, 254, 191, 191, 254, 243, 120, 191, + /* 500 */ 242, 191, 191, 191, 119, 191, 191, 191, 191, 191, + /* 510 */ 118, 191, 191, 191, 131, 191, 191, 191, 191, 191, + /* 520 */ 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + /* 530 */ 191, 191, 191, 191, 191, 191, 191, 191, 103, 192, + /* 540 */ 192, 192, 192, 87, 86, 50, 83, 85, 54, 84, + /* 550 */ 82, 79, 5, 192, 192, 192, 143, 5, 5, 143, + /* 560 */ 192, 192, 5, 197, 197, 5, 89, 134, 113, 105, + /* 570 */ 109, 114, 105, 107, 192, 104, 202, 104, 208, 193, + /* 580 */ 207, 204, 206, 203, 205, 201, 193, 192, 198, 193, + /* 590 */ 225, 192, 234, 193, 192, 194, 1, 241, 105, 239, + /* 600 */ 104, 104, 122, 122, 76, 105, 225, 109, 109, 104, + /* 610 */ 104, 104, 111, 104, 9, 107, 5, 5, 108, 5, + /* 620 */ 5, 5, 80, 15, 76, 137, 109, 137, 137, 16, /* 630 */ 5, 5, 105, 5, 5, 5, 5, 5, 5, 5, /* 640 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - /* 650 */ 109, 80, 60, 59, 0, 287, 287, 287, 287, 287, - /* 660 */ 287, 287, 287, 287, 287, 287, 21, 21, 287, 287, - /* 670 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 680 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 690 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 700 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 710 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 720 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 730 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 740 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 750 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 760 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 770 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 780 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 790 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 800 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 810 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 820 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 830 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 840 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 850 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 860 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 870 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, - /* 880 */ 287, + /* 650 */ 109, 80, 60, 59, 0, 262, 262, 262, 262, 262, + /* 660 */ 262, 262, 262, 262, 262, 262, 21, 21, 262, 262, + /* 670 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 680 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 690 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 700 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 710 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 720 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 730 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 740 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 750 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 760 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 770 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 780 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 790 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 800 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 810 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 820 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 830 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 840 */ 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + /* 850 */ 262, 262, 262, 262, 262, }; #define YY_SHIFT_COUNT (305) #define YY_SHIFT_MIN (0) @@ -382,57 +368,57 @@ static const unsigned short int yy_shift_ofst[] = { /* 0 */ 168, 79, 79, 172, 172, 139, 221, 231, 110, 110, /* 10 */ 110, 110, 110, 110, 110, 110, 110, 0, 48, 231, /* 20 */ 243, 243, 243, 243, 18, 110, 110, 110, 110, 146, - /* 30 */ 110, 110, 82, 139, 4, 4, 668, 668, 668, 231, + /* 30 */ 110, 110, 163, 139, 4, 4, 668, 668, 668, 231, /* 40 */ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, /* 50 */ 231, 231, 231, 231, 231, 231, 231, 231, 231, 243, - /* 60 */ 243, 2, 2, 2, 2, 2, 2, 2, 235, 110, - /* 70 */ 110, 21, 110, 110, 110, 242, 242, 140, 110, 110, + /* 60 */ 243, 2, 2, 2, 2, 2, 2, 2, 147, 110, + /* 70 */ 110, 21, 110, 110, 110, 248, 248, 225, 110, 110, /* 80 */ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, /* 90 */ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, /* 100 */ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, /* 110 */ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - /* 120 */ 110, 110, 110, 110, 110, 110, 110, 110, 357, 422, - /* 130 */ 422, 422, 370, 370, 370, 422, 374, 371, 378, 384, - /* 140 */ 383, 389, 394, 397, 385, 357, 422, 422, 422, 417, - /* 150 */ 139, 139, 422, 422, 434, 437, 476, 456, 461, 487, - /* 160 */ 463, 466, 417, 422, 470, 470, 422, 470, 422, 470, - /* 170 */ 422, 668, 668, 27, 100, 127, 100, 100, 53, 182, + /* 120 */ 110, 110, 110, 110, 110, 110, 110, 110, 351, 405, + /* 130 */ 405, 405, 354, 354, 354, 405, 352, 353, 355, 357, + /* 140 */ 364, 378, 385, 392, 383, 351, 405, 405, 405, 435, + /* 150 */ 139, 139, 405, 405, 456, 458, 495, 463, 462, 494, + /* 160 */ 465, 468, 435, 405, 472, 472, 405, 472, 405, 472, + /* 170 */ 405, 668, 668, 27, 100, 127, 100, 100, 53, 182, /* 180 */ 266, 266, 266, 266, 244, 261, 274, 323, 323, 323, - /* 190 */ 323, 229, 15, 272, 272, 149, 253, 305, 281, 212, - /* 200 */ 271, 278, 284, 287, 290, 372, 393, 373, 330, 304, - /* 210 */ 288, 292, 297, 299, 300, 302, 307, 310, 285, 289, - /* 220 */ 291, 191, 293, 426, 430, 347, 376, 545, 409, 550, - /* 230 */ 551, 414, 555, 558, 475, 431, 454, 464, 478, 482, - /* 240 */ 486, 459, 465, 489, 593, 491, 496, 498, 494, 483, - /* 250 */ 495, 484, 502, 504, 499, 505, 482, 507, 506, 508, - /* 260 */ 509, 538, 606, 611, 613, 614, 615, 616, 542, 608, - /* 270 */ 548, 488, 517, 517, 612, 490, 492, 517, 625, 626, + /* 190 */ 323, 229, 15, 272, 272, 265, 96, 255, 269, 280, + /* 200 */ 281, 287, 288, 289, 290, 371, 372, 260, 305, 302, + /* 210 */ 278, 291, 297, 298, 306, 307, 309, 313, 268, 285, + /* 220 */ 292, 319, 294, 419, 427, 359, 375, 547, 413, 552, + /* 230 */ 553, 416, 557, 560, 477, 433, 455, 464, 457, 466, + /* 240 */ 471, 461, 467, 473, 595, 496, 493, 497, 498, 480, + /* 250 */ 499, 481, 500, 505, 501, 506, 466, 507, 508, 509, + /* 260 */ 510, 528, 605, 611, 612, 614, 615, 616, 542, 608, + /* 270 */ 548, 488, 517, 517, 613, 490, 491, 517, 625, 626, /* 280 */ 527, 517, 628, 629, 630, 631, 632, 633, 634, 635, /* 290 */ 636, 637, 638, 639, 640, 641, 642, 643, 644, 541, /* 300 */ 571, 645, 646, 592, 594, 654, }; #define YY_REDUCE_COUNT (172) -#define YY_REDUCE_MIN (-276) -#define YY_REDUCE_MAX (369) +#define YY_REDUCE_MIN (-251) +#define YY_REDUCE_MAX (402) static const short yy_reduce_ofst[] = { - /* 0 */ -184, -52, -52, 41, 41, 96, -274, -254, -201, -153, - /* 10 */ -198, -145, -98, -33, 118, 124, 125, -170, -212, -276, - /* 20 */ -216, -193, -173, -24, -59, -133, -210, -81, -12, -114, - /* 30 */ 31, 1, 63, 12, 77, 134, -23, 103, 153, -271, - /* 40 */ -268, -63, -45, -32, -8, 5, 52, 137, 143, 156, - /* 50 */ 160, 164, 165, 166, 167, 169, 170, 171, 173, 97, - /* 60 */ 142, 192, 196, 198, 199, 200, 201, 202, 197, 239, - /* 70 */ 241, 183, 245, 246, 247, 176, 177, 203, 248, 249, - /* 80 */ 251, 252, 254, 255, 256, 257, 258, 259, 260, 262, - /* 90 */ 263, 264, 265, 267, 268, 269, 270, 273, 275, 276, - /* 100 */ 277, 279, 280, 282, 283, 286, 294, 295, 296, 298, - /* 110 */ 301, 303, 306, 308, 309, 311, 312, 313, 314, 315, - /* 120 */ 316, 317, 318, 319, 320, 321, 322, 324, 218, 325, - /* 130 */ 326, 327, 209, 211, 215, 328, 225, 232, 236, 238, - /* 140 */ 250, 329, 331, 333, 335, 332, 334, 336, 337, 338, - /* 150 */ 339, 340, 341, 342, 343, 345, 344, 346, 348, 351, - /* 160 */ 352, 354, 350, 349, 353, 356, 355, 364, 366, 367, - /* 170 */ 369, 361, 368, + /* 0 */ -159, -27, -27, 66, 66, 121, -249, -229, -176, -128, + /* 10 */ -173, -120, -73, -8, 148, 149, 156, -145, -187, -251, + /* 20 */ -191, -168, -148, 1, -34, -108, -185, -56, 13, -89, + /* 30 */ 56, 22, 88, 20, 102, 170, 19, 128, 164, -246, + /* 40 */ -243, -93, 30, 44, 77, 104, 150, 159, 176, 188, + /* 50 */ 189, 190, 191, 192, 193, 194, 195, 196, 197, 17, + /* 60 */ 213, 39, 206, 223, 224, 226, 227, 228, 218, 267, + /* 70 */ 270, 207, 271, 273, 275, 198, 201, 222, 276, 277, + /* 80 */ 279, 282, 283, 284, 286, 293, 295, 296, 299, 300, + /* 90 */ 301, 303, 304, 308, 310, 311, 312, 314, 315, 316, + /* 100 */ 317, 318, 320, 321, 322, 324, 325, 326, 327, 328, + /* 110 */ 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, + /* 120 */ 339, 340, 341, 342, 343, 344, 345, 346, 235, 347, + /* 130 */ 348, 349, 234, 239, 242, 350, 233, 230, 238, 241, + /* 140 */ 254, 258, 356, 232, 360, 358, 361, 362, 363, 365, + /* 150 */ 366, 367, 368, 369, 370, 373, 376, 374, 379, 380, + /* 160 */ 377, 384, 381, 382, 386, 393, 395, 396, 399, 400, + /* 170 */ 402, 390, 401, }; static const YYACTIONTYPE yy_default[] = { /* 0 */ 757, 869, 815, 881, 803, 812, 1007, 1007, 757, 757, @@ -660,32 +646,6 @@ static const YYCODETYPE yyFallback[] = { 1, /* STATEMENT => ID */ 1, /* TRIGGER => ID */ 1, /* VIEW => ID */ - 1, /* COUNT => ID */ - 1, /* SUM => ID */ - 1, /* AVG => ID */ - 1, /* MIN => ID */ - 1, /* MAX => ID */ - 1, /* FIRST => ID */ - 1, /* LAST => ID */ - 1, /* TOP => ID */ - 1, /* BOTTOM => ID */ - 1, /* STDDEV => ID */ - 1, /* PERCENTILE => ID */ - 1, /* APERCENTILE => ID */ - 1, /* LEASTSQUARES => ID */ - 1, /* HISTOGRAM => ID */ - 1, /* DIFF => ID */ - 1, /* SPREAD => ID */ - 1, /* TWA => ID */ - 1, /* INTERP => ID */ - 1, /* LAST_ROW => ID */ - 1, /* RATE => ID */ - 1, /* IRATE => ID */ - 1, /* SUM_RATE => ID */ - 1, /* SUM_IRATE => ID */ - 1, /* AVG_RATE => ID */ - 1, /* AVG_IRATE => ID */ - 1, /* TBID => ID */ 1, /* SEMI => ID */ 1, /* NONE => ID */ 1, /* PREV => ID */ @@ -737,7 +697,6 @@ struct yyParser { int yyerrcnt; /* Shifts left before out of the error */ #endif ParseARG_SDECL /* A place to hold %extra_argument */ - ParseCTX_SDECL /* A place to hold %extra_context */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ @@ -960,118 +919,93 @@ static const char *const yyTokenName[] = { /* 172 */ "STATEMENT", /* 173 */ "TRIGGER", /* 174 */ "VIEW", - /* 175 */ "COUNT", - /* 176 */ "SUM", - /* 177 */ "AVG", - /* 178 */ "MIN", - /* 179 */ "MAX", - /* 180 */ "FIRST", - /* 181 */ "LAST", - /* 182 */ "TOP", - /* 183 */ "BOTTOM", - /* 184 */ "STDDEV", - /* 185 */ "PERCENTILE", - /* 186 */ "APERCENTILE", - /* 187 */ "LEASTSQUARES", - /* 188 */ "HISTOGRAM", - /* 189 */ "DIFF", - /* 190 */ "SPREAD", - /* 191 */ "TWA", - /* 192 */ "INTERP", - /* 193 */ "LAST_ROW", - /* 194 */ "RATE", - /* 195 */ "IRATE", - /* 196 */ "SUM_RATE", - /* 197 */ "SUM_IRATE", - /* 198 */ "AVG_RATE", - /* 199 */ "AVG_IRATE", - /* 200 */ "TBID", - /* 201 */ "SEMI", - /* 202 */ "NONE", - /* 203 */ "PREV", - /* 204 */ "LINEAR", - /* 205 */ "IMPORT", - /* 206 */ "METRIC", - /* 207 */ "TBNAME", - /* 208 */ "JOIN", - /* 209 */ "METRICS", - /* 210 */ "INSERT", - /* 211 */ "INTO", - /* 212 */ "VALUES", - /* 213 */ "program", - /* 214 */ "cmd", - /* 215 */ "dbPrefix", - /* 216 */ "ids", - /* 217 */ "cpxName", - /* 218 */ "ifexists", - /* 219 */ "alter_db_optr", - /* 220 */ "alter_topic_optr", - /* 221 */ "acct_optr", - /* 222 */ "ifnotexists", - /* 223 */ "db_optr", - /* 224 */ "topic_optr", - /* 225 */ "pps", - /* 226 */ "tseries", - /* 227 */ "dbs", - /* 228 */ "streams", - /* 229 */ "storage", - /* 230 */ "qtime", - /* 231 */ "users", - /* 232 */ "conns", - /* 233 */ "state", - /* 234 */ "keep", - /* 235 */ "tagitemlist", - /* 236 */ "cache", - /* 237 */ "replica", - /* 238 */ "quorum", - /* 239 */ "days", - /* 240 */ "minrows", - /* 241 */ "maxrows", - /* 242 */ "blocks", - /* 243 */ "ctime", - /* 244 */ "wal", - /* 245 */ "fsync", - /* 246 */ "comp", - /* 247 */ "prec", - /* 248 */ "update", - /* 249 */ "cachelast", - /* 250 */ "partitions", - /* 251 */ "typename", - /* 252 */ "signed", - /* 253 */ "create_table_args", - /* 254 */ "create_stable_args", - /* 255 */ "create_table_list", - /* 256 */ "create_from_stable", - /* 257 */ "columnlist", - /* 258 */ "tagNamelist", - /* 259 */ "select", - /* 260 */ "column", - /* 261 */ "tagitem", - /* 262 */ "selcollist", - /* 263 */ "from", - /* 264 */ "where_opt", - /* 265 */ "interval_opt", - /* 266 */ "fill_opt", - /* 267 */ "sliding_opt", - /* 268 */ "groupby_opt", - /* 269 */ "orderby_opt", - /* 270 */ "having_opt", - /* 271 */ "slimit_opt", - /* 272 */ "limit_opt", - /* 273 */ "union", - /* 274 */ "sclp", - /* 275 */ "distinct", - /* 276 */ "expr", - /* 277 */ "as", - /* 278 */ "tablelist", - /* 279 */ "tmvar", - /* 280 */ "sortlist", - /* 281 */ "sortitem", - /* 282 */ "item", - /* 283 */ "sortorder", - /* 284 */ "grouplist", - /* 285 */ "exprlist", - /* 286 */ "expritem", + /* 175 */ "SEMI", + /* 176 */ "NONE", + /* 177 */ "PREV", + /* 178 */ "LINEAR", + /* 179 */ "IMPORT", + /* 180 */ "METRIC", + /* 181 */ "TBNAME", + /* 182 */ "JOIN", + /* 183 */ "METRICS", + /* 184 */ "INSERT", + /* 185 */ "INTO", + /* 186 */ "VALUES", + /* 187 */ "error", + /* 188 */ "program", + /* 189 */ "cmd", + /* 190 */ "dbPrefix", + /* 191 */ "ids", + /* 192 */ "cpxName", + /* 193 */ "ifexists", + /* 194 */ "alter_db_optr", + /* 195 */ "alter_topic_optr", + /* 196 */ "acct_optr", + /* 197 */ "ifnotexists", + /* 198 */ "db_optr", + /* 199 */ "topic_optr", + /* 200 */ "pps", + /* 201 */ "tseries", + /* 202 */ "dbs", + /* 203 */ "streams", + /* 204 */ "storage", + /* 205 */ "qtime", + /* 206 */ "users", + /* 207 */ "conns", + /* 208 */ "state", + /* 209 */ "keep", + /* 210 */ "tagitemlist", + /* 211 */ "cache", + /* 212 */ "replica", + /* 213 */ "quorum", + /* 214 */ "days", + /* 215 */ "minrows", + /* 216 */ "maxrows", + /* 217 */ "blocks", + /* 218 */ "ctime", + /* 219 */ "wal", + /* 220 */ "fsync", + /* 221 */ "comp", + /* 222 */ "prec", + /* 223 */ "update", + /* 224 */ "cachelast", + /* 225 */ "partitions", + /* 226 */ "typename", + /* 227 */ "signed", + /* 228 */ "create_table_args", + /* 229 */ "create_stable_args", + /* 230 */ "create_table_list", + /* 231 */ "create_from_stable", + /* 232 */ "columnlist", + /* 233 */ "tagNamelist", + /* 234 */ "select", + /* 235 */ "column", + /* 236 */ "tagitem", + /* 237 */ "selcollist", + /* 238 */ "from", + /* 239 */ "where_opt", + /* 240 */ "interval_opt", + /* 241 */ "fill_opt", + /* 242 */ "sliding_opt", + /* 243 */ "groupby_opt", + /* 244 */ "orderby_opt", + /* 245 */ "having_opt", + /* 246 */ "slimit_opt", + /* 247 */ "limit_opt", + /* 248 */ "union", + /* 249 */ "sclp", + /* 250 */ "distinct", + /* 251 */ "expr", + /* 252 */ "as", + /* 253 */ "tablelist", + /* 254 */ "tmvar", + /* 255 */ "sortlist", + /* 256 */ "sortitem", + /* 257 */ "item", + /* 258 */ "sortorder", + /* 259 */ "grouplist", + /* 260 */ "exprlist", + /* 261 */ "expritem", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -1390,29 +1324,28 @@ static int yyGrowStack(yyParser *p){ /* Initialize a new parser that has already been allocated. */ -void ParseInit(void *yypRawParser ParseCTX_PDECL){ - yyParser *yypParser = (yyParser*)yypRawParser; - ParseCTX_STORE +void ParseInit(void *yypParser){ + yyParser *pParser = (yyParser*)yypParser; #ifdef YYTRACKMAXSTACKDEPTH - yypParser->yyhwm = 0; + pParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 - yypParser->yytos = NULL; - yypParser->yystack = NULL; - yypParser->yystksz = 0; - if( yyGrowStack(yypParser) ){ - yypParser->yystack = &yypParser->yystk0; - yypParser->yystksz = 1; + pParser->yytos = NULL; + pParser->yystack = NULL; + pParser->yystksz = 0; + if( yyGrowStack(pParser) ){ + pParser->yystack = &pParser->yystk0; + pParser->yystksz = 1; } #endif #ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; + pParser->yyerrcnt = -1; #endif - yypParser->yytos = yypParser->yystack; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; + pParser->yytos = pParser->yystack; + pParser->yystack[0].stateno = 0; + pParser->yystack[0].major = 0; #if YYSTACKDEPTH>0 - yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; + pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; #endif } @@ -1429,14 +1362,11 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ - yyParser *yypParser; - yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( yypParser ){ - ParseCTX_STORE - ParseInit(yypParser ParseCTX_PARAM); - } - return (void*)yypParser; +void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ + yyParser *pParser; + pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + if( pParser ) ParseInit(pParser); + return pParser; } #endif /* Parse_ENGINEALWAYSONSTACK */ @@ -1453,8 +1383,7 @@ static void yy_destructor( YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ - ParseARG_FETCH - ParseCTX_FETCH + ParseARG_FETCH; switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen @@ -1467,52 +1396,52 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 234: /* keep */ - case 235: /* tagitemlist */ - case 257: /* columnlist */ - case 258: /* tagNamelist */ - case 266: /* fill_opt */ - case 268: /* groupby_opt */ - case 269: /* orderby_opt */ - case 280: /* sortlist */ - case 284: /* grouplist */ + case 209: /* keep */ + case 210: /* tagitemlist */ + case 232: /* columnlist */ + case 233: /* tagNamelist */ + case 241: /* fill_opt */ + case 243: /* groupby_opt */ + case 244: /* orderby_opt */ + case 255: /* sortlist */ + case 259: /* grouplist */ { -taosArrayDestroy((yypminor->yy207)); +taosArrayDestroy((yypminor->yy429)); } break; - case 255: /* create_table_list */ + case 230: /* create_table_list */ { -destroyCreateTableSql((yypminor->yy414)); +destroyCreateTableSql((yypminor->yy310)); } break; - case 259: /* select */ + case 234: /* select */ { -doDestroyQuerySql((yypminor->yy526)); +doDestroyQuerySql((yypminor->yy372)); } break; - case 262: /* selcollist */ - case 274: /* sclp */ - case 285: /* exprlist */ + case 237: /* selcollist */ + case 249: /* sclp */ + case 260: /* exprlist */ { -tSqlExprListDestroy((yypminor->yy178)); +tSqlExprListDestroy((yypminor->yy170)); } break; - case 264: /* where_opt */ - case 270: /* having_opt */ - case 276: /* expr */ - case 286: /* expritem */ + case 239: /* where_opt */ + case 245: /* having_opt */ + case 251: /* expr */ + case 261: /* expritem */ { -tSqlExprDestroy((yypminor->yy484)); +tSqlExprDestroy((yypminor->yy282)); } break; - case 273: /* union */ + case 248: /* union */ { -destroyAllSelectClause((yypminor->yy441)); +destroyAllSelectClause((yypminor->yy141)); } break; - case 281: /* sortitem */ + case 256: /* sortitem */ { -tVariantDestroy(&(yypminor->yy232)); +tVariantDestroy(&(yypminor->yy218)); } break; /********* End destructor definitions *****************************************/ @@ -1624,12 +1553,13 @@ int ParseCoverage(FILE *out){ ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ -static YYACTIONTYPE yy_find_shift_action( - YYCODETYPE iLookAhead, /* The look-ahead token */ - YYACTIONTYPE stateno /* Current state number */ +static unsigned int yy_find_shift_action( + yyParser *pParser, /* The parser */ + YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; - + int stateno = pParser->yytos->stateno; + if( stateno>YY_MAX_SHIFT ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); #if defined(YYCOVERAGE) @@ -1637,19 +1567,15 @@ static YYACTIONTYPE yy_find_shift_action( #endif do{ i = yy_shift_ofst[stateno]; - assert( i>=0 ); - assert( i<=YY_ACTTAB_COUNT ); - assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); + assert( i>=0 && i+YYNTOKEN<=sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - assert( i<(int)YY_NLOOKAHEAD ); if( yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - assert( iLookAhead %s\n", @@ -1664,8 +1590,15 @@ static YYACTIONTYPE yy_find_shift_action( #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); - if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j0 + ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", @@ -1679,7 +1612,6 @@ static YYACTIONTYPE yy_find_shift_action( #endif /* YYWILDCARD */ return yy_default[stateno]; }else{ - assert( i>=0 && iyytos; - yytos->stateno = yyNewState; - yytos->major = yyMajor; + yytos->stateno = (YYACTIONTYPE)yyNewState; + yytos->major = (YYCODETYPE)yyMajor; yytos->minor.yy0 = yyMinor; yyTraceShift(yypParser, yyNewState, "Shift"); } -/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side -** of that rule */ -static const YYCODETYPE yyRuleInfoLhs[] = { - 213, /* (0) program ::= cmd */ - 214, /* (1) cmd ::= SHOW DATABASES */ - 214, /* (2) cmd ::= SHOW TOPICS */ - 214, /* (3) cmd ::= SHOW MNODES */ - 214, /* (4) cmd ::= SHOW DNODES */ - 214, /* (5) cmd ::= SHOW ACCOUNTS */ - 214, /* (6) cmd ::= SHOW USERS */ - 214, /* (7) cmd ::= SHOW MODULES */ - 214, /* (8) cmd ::= SHOW QUERIES */ - 214, /* (9) cmd ::= SHOW CONNECTIONS */ - 214, /* (10) cmd ::= SHOW STREAMS */ - 214, /* (11) cmd ::= SHOW VARIABLES */ - 214, /* (12) cmd ::= SHOW SCORES */ - 214, /* (13) cmd ::= SHOW GRANTS */ - 214, /* (14) cmd ::= SHOW VNODES */ - 214, /* (15) cmd ::= SHOW VNODES IPTOKEN */ - 215, /* (16) dbPrefix ::= */ - 215, /* (17) dbPrefix ::= ids DOT */ - 217, /* (18) cpxName ::= */ - 217, /* (19) cpxName ::= DOT ids */ - 214, /* (20) cmd ::= SHOW CREATE TABLE ids cpxName */ - 214, /* (21) cmd ::= SHOW CREATE DATABASE ids */ - 214, /* (22) cmd ::= SHOW dbPrefix TABLES */ - 214, /* (23) cmd ::= SHOW dbPrefix TABLES LIKE ids */ - 214, /* (24) cmd ::= SHOW dbPrefix STABLES */ - 214, /* (25) cmd ::= SHOW dbPrefix STABLES LIKE ids */ - 214, /* (26) cmd ::= SHOW dbPrefix VGROUPS */ - 214, /* (27) cmd ::= SHOW dbPrefix VGROUPS ids */ - 214, /* (28) cmd ::= DROP TABLE ifexists ids cpxName */ - 214, /* (29) cmd ::= DROP STABLE ifexists ids cpxName */ - 214, /* (30) cmd ::= DROP DATABASE ifexists ids */ - 214, /* (31) cmd ::= DROP TOPIC ifexists ids */ - 214, /* (32) cmd ::= DROP DNODE ids */ - 214, /* (33) cmd ::= DROP USER ids */ - 214, /* (34) cmd ::= DROP ACCOUNT ids */ - 214, /* (35) cmd ::= USE ids */ - 214, /* (36) cmd ::= DESCRIBE ids cpxName */ - 214, /* (37) cmd ::= ALTER USER ids PASS ids */ - 214, /* (38) cmd ::= ALTER USER ids PRIVILEGE ids */ - 214, /* (39) cmd ::= ALTER DNODE ids ids */ - 214, /* (40) cmd ::= ALTER DNODE ids ids ids */ - 214, /* (41) cmd ::= ALTER LOCAL ids */ - 214, /* (42) cmd ::= ALTER LOCAL ids ids */ - 214, /* (43) cmd ::= ALTER DATABASE ids alter_db_optr */ - 214, /* (44) cmd ::= ALTER TOPIC ids alter_topic_optr */ - 214, /* (45) cmd ::= ALTER ACCOUNT ids acct_optr */ - 214, /* (46) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ - 216, /* (47) ids ::= ID */ - 216, /* (48) ids ::= STRING */ - 218, /* (49) ifexists ::= IF EXISTS */ - 218, /* (50) ifexists ::= */ - 222, /* (51) ifnotexists ::= IF NOT EXISTS */ - 222, /* (52) ifnotexists ::= */ - 214, /* (53) cmd ::= CREATE DNODE ids */ - 214, /* (54) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ - 214, /* (55) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ - 214, /* (56) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ - 214, /* (57) cmd ::= CREATE USER ids PASS ids */ - 225, /* (58) pps ::= */ - 225, /* (59) pps ::= PPS INTEGER */ - 226, /* (60) tseries ::= */ - 226, /* (61) tseries ::= TSERIES INTEGER */ - 227, /* (62) dbs ::= */ - 227, /* (63) dbs ::= DBS INTEGER */ - 228, /* (64) streams ::= */ - 228, /* (65) streams ::= STREAMS INTEGER */ - 229, /* (66) storage ::= */ - 229, /* (67) storage ::= STORAGE INTEGER */ - 230, /* (68) qtime ::= */ - 230, /* (69) qtime ::= QTIME INTEGER */ - 231, /* (70) users ::= */ - 231, /* (71) users ::= USERS INTEGER */ - 232, /* (72) conns ::= */ - 232, /* (73) conns ::= CONNS INTEGER */ - 233, /* (74) state ::= */ - 233, /* (75) state ::= STATE ids */ - 221, /* (76) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ - 234, /* (77) keep ::= KEEP tagitemlist */ - 236, /* (78) cache ::= CACHE INTEGER */ - 237, /* (79) replica ::= REPLICA INTEGER */ - 238, /* (80) quorum ::= QUORUM INTEGER */ - 239, /* (81) days ::= DAYS INTEGER */ - 240, /* (82) minrows ::= MINROWS INTEGER */ - 241, /* (83) maxrows ::= MAXROWS INTEGER */ - 242, /* (84) blocks ::= BLOCKS INTEGER */ - 243, /* (85) ctime ::= CTIME INTEGER */ - 244, /* (86) wal ::= WAL INTEGER */ - 245, /* (87) fsync ::= FSYNC INTEGER */ - 246, /* (88) comp ::= COMP INTEGER */ - 247, /* (89) prec ::= PRECISION STRING */ - 248, /* (90) update ::= UPDATE INTEGER */ - 249, /* (91) cachelast ::= CACHELAST INTEGER */ - 250, /* (92) partitions ::= PARTITIONS INTEGER */ - 223, /* (93) db_optr ::= */ - 223, /* (94) db_optr ::= db_optr cache */ - 223, /* (95) db_optr ::= db_optr replica */ - 223, /* (96) db_optr ::= db_optr quorum */ - 223, /* (97) db_optr ::= db_optr days */ - 223, /* (98) db_optr ::= db_optr minrows */ - 223, /* (99) db_optr ::= db_optr maxrows */ - 223, /* (100) db_optr ::= db_optr blocks */ - 223, /* (101) db_optr ::= db_optr ctime */ - 223, /* (102) db_optr ::= db_optr wal */ - 223, /* (103) db_optr ::= db_optr fsync */ - 223, /* (104) db_optr ::= db_optr comp */ - 223, /* (105) db_optr ::= db_optr prec */ - 223, /* (106) db_optr ::= db_optr keep */ - 223, /* (107) db_optr ::= db_optr update */ - 223, /* (108) db_optr ::= db_optr cachelast */ - 224, /* (109) topic_optr ::= db_optr */ - 224, /* (110) topic_optr ::= topic_optr partitions */ - 219, /* (111) alter_db_optr ::= */ - 219, /* (112) alter_db_optr ::= alter_db_optr replica */ - 219, /* (113) alter_db_optr ::= alter_db_optr quorum */ - 219, /* (114) alter_db_optr ::= alter_db_optr keep */ - 219, /* (115) alter_db_optr ::= alter_db_optr blocks */ - 219, /* (116) alter_db_optr ::= alter_db_optr comp */ - 219, /* (117) alter_db_optr ::= alter_db_optr wal */ - 219, /* (118) alter_db_optr ::= alter_db_optr fsync */ - 219, /* (119) alter_db_optr ::= alter_db_optr update */ - 219, /* (120) alter_db_optr ::= alter_db_optr cachelast */ - 220, /* (121) alter_topic_optr ::= alter_db_optr */ - 220, /* (122) alter_topic_optr ::= alter_topic_optr partitions */ - 251, /* (123) typename ::= ids */ - 251, /* (124) typename ::= ids LP signed RP */ - 251, /* (125) typename ::= ids UNSIGNED */ - 252, /* (126) signed ::= INTEGER */ - 252, /* (127) signed ::= PLUS INTEGER */ - 252, /* (128) signed ::= MINUS INTEGER */ - 214, /* (129) cmd ::= CREATE TABLE create_table_args */ - 214, /* (130) cmd ::= CREATE TABLE create_stable_args */ - 214, /* (131) cmd ::= CREATE STABLE create_stable_args */ - 214, /* (132) cmd ::= CREATE TABLE create_table_list */ - 255, /* (133) create_table_list ::= create_from_stable */ - 255, /* (134) create_table_list ::= create_table_list create_from_stable */ - 253, /* (135) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ - 254, /* (136) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ - 256, /* (137) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ - 256, /* (138) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ - 258, /* (139) tagNamelist ::= tagNamelist COMMA ids */ - 258, /* (140) tagNamelist ::= ids */ - 253, /* (141) create_table_args ::= ifnotexists ids cpxName AS select */ - 257, /* (142) columnlist ::= columnlist COMMA column */ - 257, /* (143) columnlist ::= column */ - 260, /* (144) column ::= ids typename */ - 235, /* (145) tagitemlist ::= tagitemlist COMMA tagitem */ - 235, /* (146) tagitemlist ::= tagitem */ - 261, /* (147) tagitem ::= INTEGER */ - 261, /* (148) tagitem ::= FLOAT */ - 261, /* (149) tagitem ::= STRING */ - 261, /* (150) tagitem ::= BOOL */ - 261, /* (151) tagitem ::= NULL */ - 261, /* (152) tagitem ::= MINUS INTEGER */ - 261, /* (153) tagitem ::= MINUS FLOAT */ - 261, /* (154) tagitem ::= PLUS INTEGER */ - 261, /* (155) tagitem ::= PLUS FLOAT */ - 259, /* (156) select ::= SELECT selcollist from where_opt interval_opt fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ - 273, /* (157) union ::= select */ - 273, /* (158) union ::= LP union RP */ - 273, /* (159) union ::= union UNION ALL select */ - 273, /* (160) union ::= union UNION ALL LP select RP */ - 214, /* (161) cmd ::= union */ - 259, /* (162) select ::= SELECT selcollist */ - 274, /* (163) sclp ::= selcollist COMMA */ - 274, /* (164) sclp ::= */ - 262, /* (165) selcollist ::= sclp distinct expr as */ - 262, /* (166) selcollist ::= sclp STAR */ - 277, /* (167) as ::= AS ids */ - 277, /* (168) as ::= ids */ - 277, /* (169) as ::= */ - 275, /* (170) distinct ::= DISTINCT */ - 275, /* (171) distinct ::= */ - 263, /* (172) from ::= FROM tablelist */ - 278, /* (173) tablelist ::= ids cpxName */ - 278, /* (174) tablelist ::= ids cpxName ids */ - 278, /* (175) tablelist ::= tablelist COMMA ids cpxName */ - 278, /* (176) tablelist ::= tablelist COMMA ids cpxName ids */ - 279, /* (177) tmvar ::= VARIABLE */ - 265, /* (178) interval_opt ::= INTERVAL LP tmvar RP */ - 265, /* (179) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ - 265, /* (180) interval_opt ::= */ - 266, /* (181) fill_opt ::= */ - 266, /* (182) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ - 266, /* (183) fill_opt ::= FILL LP ID RP */ - 267, /* (184) sliding_opt ::= SLIDING LP tmvar RP */ - 267, /* (185) sliding_opt ::= */ - 269, /* (186) orderby_opt ::= */ - 269, /* (187) orderby_opt ::= ORDER BY sortlist */ - 280, /* (188) sortlist ::= sortlist COMMA item sortorder */ - 280, /* (189) sortlist ::= item sortorder */ - 282, /* (190) item ::= ids cpxName */ - 283, /* (191) sortorder ::= ASC */ - 283, /* (192) sortorder ::= DESC */ - 283, /* (193) sortorder ::= */ - 268, /* (194) groupby_opt ::= */ - 268, /* (195) groupby_opt ::= GROUP BY grouplist */ - 284, /* (196) grouplist ::= grouplist COMMA item */ - 284, /* (197) grouplist ::= item */ - 270, /* (198) having_opt ::= */ - 270, /* (199) having_opt ::= HAVING expr */ - 272, /* (200) limit_opt ::= */ - 272, /* (201) limit_opt ::= LIMIT signed */ - 272, /* (202) limit_opt ::= LIMIT signed OFFSET signed */ - 272, /* (203) limit_opt ::= LIMIT signed COMMA signed */ - 271, /* (204) slimit_opt ::= */ - 271, /* (205) slimit_opt ::= SLIMIT signed */ - 271, /* (206) slimit_opt ::= SLIMIT signed SOFFSET signed */ - 271, /* (207) slimit_opt ::= SLIMIT signed COMMA signed */ - 264, /* (208) where_opt ::= */ - 264, /* (209) where_opt ::= WHERE expr */ - 276, /* (210) expr ::= LP expr RP */ - 276, /* (211) expr ::= ID */ - 276, /* (212) expr ::= ID DOT ID */ - 276, /* (213) expr ::= ID DOT STAR */ - 276, /* (214) expr ::= INTEGER */ - 276, /* (215) expr ::= MINUS INTEGER */ - 276, /* (216) expr ::= PLUS INTEGER */ - 276, /* (217) expr ::= FLOAT */ - 276, /* (218) expr ::= MINUS FLOAT */ - 276, /* (219) expr ::= PLUS FLOAT */ - 276, /* (220) expr ::= STRING */ - 276, /* (221) expr ::= NOW */ - 276, /* (222) expr ::= VARIABLE */ - 276, /* (223) expr ::= BOOL */ - 276, /* (224) expr ::= ID LP exprlist RP */ - 276, /* (225) expr ::= ID LP STAR RP */ - 276, /* (226) expr ::= expr IS NULL */ - 276, /* (227) expr ::= expr IS NOT NULL */ - 276, /* (228) expr ::= expr LT expr */ - 276, /* (229) expr ::= expr GT expr */ - 276, /* (230) expr ::= expr LE expr */ - 276, /* (231) expr ::= expr GE expr */ - 276, /* (232) expr ::= expr NE expr */ - 276, /* (233) expr ::= expr EQ expr */ - 276, /* (234) expr ::= expr BETWEEN expr AND expr */ - 276, /* (235) expr ::= expr AND expr */ - 276, /* (236) expr ::= expr OR expr */ - 276, /* (237) expr ::= expr PLUS expr */ - 276, /* (238) expr ::= expr MINUS expr */ - 276, /* (239) expr ::= expr STAR expr */ - 276, /* (240) expr ::= expr SLASH expr */ - 276, /* (241) expr ::= expr REM expr */ - 276, /* (242) expr ::= expr LIKE expr */ - 276, /* (243) expr ::= expr IN LP exprlist RP */ - 285, /* (244) exprlist ::= exprlist COMMA expritem */ - 285, /* (245) exprlist ::= expritem */ - 286, /* (246) expritem ::= expr */ - 286, /* (247) expritem ::= */ - 214, /* (248) cmd ::= RESET QUERY CACHE */ - 214, /* (249) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ - 214, /* (250) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ - 214, /* (251) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ - 214, /* (252) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ - 214, /* (253) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ - 214, /* (254) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ - 214, /* (255) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ - 214, /* (256) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ - 214, /* (257) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ - 214, /* (258) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ - 214, /* (259) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ - 214, /* (260) cmd ::= KILL CONNECTION INTEGER */ - 214, /* (261) cmd ::= KILL STREAM INTEGER COLON INTEGER */ - 214, /* (262) cmd ::= KILL QUERY INTEGER COLON INTEGER */ -}; - -/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number -** of symbols on the right-hand side of that rule. */ -static const signed char yyRuleInfoNRhs[] = { - -1, /* (0) program ::= cmd */ - -2, /* (1) cmd ::= SHOW DATABASES */ - -2, /* (2) cmd ::= SHOW TOPICS */ - -2, /* (3) cmd ::= SHOW MNODES */ - -2, /* (4) cmd ::= SHOW DNODES */ - -2, /* (5) cmd ::= SHOW ACCOUNTS */ - -2, /* (6) cmd ::= SHOW USERS */ - -2, /* (7) cmd ::= SHOW MODULES */ - -2, /* (8) cmd ::= SHOW QUERIES */ - -2, /* (9) cmd ::= SHOW CONNECTIONS */ - -2, /* (10) cmd ::= SHOW STREAMS */ - -2, /* (11) cmd ::= SHOW VARIABLES */ - -2, /* (12) cmd ::= SHOW SCORES */ - -2, /* (13) cmd ::= SHOW GRANTS */ - -2, /* (14) cmd ::= SHOW VNODES */ - -3, /* (15) cmd ::= SHOW VNODES IPTOKEN */ - 0, /* (16) dbPrefix ::= */ - -2, /* (17) dbPrefix ::= ids DOT */ - 0, /* (18) cpxName ::= */ - -2, /* (19) cpxName ::= DOT ids */ - -5, /* (20) cmd ::= SHOW CREATE TABLE ids cpxName */ - -4, /* (21) cmd ::= SHOW CREATE DATABASE ids */ - -3, /* (22) cmd ::= SHOW dbPrefix TABLES */ - -5, /* (23) cmd ::= SHOW dbPrefix TABLES LIKE ids */ - -3, /* (24) cmd ::= SHOW dbPrefix STABLES */ - -5, /* (25) cmd ::= SHOW dbPrefix STABLES LIKE ids */ - -3, /* (26) cmd ::= SHOW dbPrefix VGROUPS */ - -4, /* (27) cmd ::= SHOW dbPrefix VGROUPS ids */ - -5, /* (28) cmd ::= DROP TABLE ifexists ids cpxName */ - -5, /* (29) cmd ::= DROP STABLE ifexists ids cpxName */ - -4, /* (30) cmd ::= DROP DATABASE ifexists ids */ - -4, /* (31) cmd ::= DROP TOPIC ifexists ids */ - -3, /* (32) cmd ::= DROP DNODE ids */ - -3, /* (33) cmd ::= DROP USER ids */ - -3, /* (34) cmd ::= DROP ACCOUNT ids */ - -2, /* (35) cmd ::= USE ids */ - -3, /* (36) cmd ::= DESCRIBE ids cpxName */ - -5, /* (37) cmd ::= ALTER USER ids PASS ids */ - -5, /* (38) cmd ::= ALTER USER ids PRIVILEGE ids */ - -4, /* (39) cmd ::= ALTER DNODE ids ids */ - -5, /* (40) cmd ::= ALTER DNODE ids ids ids */ - -3, /* (41) cmd ::= ALTER LOCAL ids */ - -4, /* (42) cmd ::= ALTER LOCAL ids ids */ - -4, /* (43) cmd ::= ALTER DATABASE ids alter_db_optr */ - -4, /* (44) cmd ::= ALTER TOPIC ids alter_topic_optr */ - -4, /* (45) cmd ::= ALTER ACCOUNT ids acct_optr */ - -6, /* (46) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ - -1, /* (47) ids ::= ID */ - -1, /* (48) ids ::= STRING */ - -2, /* (49) ifexists ::= IF EXISTS */ - 0, /* (50) ifexists ::= */ - -3, /* (51) ifnotexists ::= IF NOT EXISTS */ - 0, /* (52) ifnotexists ::= */ - -3, /* (53) cmd ::= CREATE DNODE ids */ - -6, /* (54) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ - -5, /* (55) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ - -5, /* (56) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ - -5, /* (57) cmd ::= CREATE USER ids PASS ids */ - 0, /* (58) pps ::= */ - -2, /* (59) pps ::= PPS INTEGER */ - 0, /* (60) tseries ::= */ - -2, /* (61) tseries ::= TSERIES INTEGER */ - 0, /* (62) dbs ::= */ - -2, /* (63) dbs ::= DBS INTEGER */ - 0, /* (64) streams ::= */ - -2, /* (65) streams ::= STREAMS INTEGER */ - 0, /* (66) storage ::= */ - -2, /* (67) storage ::= STORAGE INTEGER */ - 0, /* (68) qtime ::= */ - -2, /* (69) qtime ::= QTIME INTEGER */ - 0, /* (70) users ::= */ - -2, /* (71) users ::= USERS INTEGER */ - 0, /* (72) conns ::= */ - -2, /* (73) conns ::= CONNS INTEGER */ - 0, /* (74) state ::= */ - -2, /* (75) state ::= STATE ids */ - -9, /* (76) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ - -2, /* (77) keep ::= KEEP tagitemlist */ - -2, /* (78) cache ::= CACHE INTEGER */ - -2, /* (79) replica ::= REPLICA INTEGER */ - -2, /* (80) quorum ::= QUORUM INTEGER */ - -2, /* (81) days ::= DAYS INTEGER */ - -2, /* (82) minrows ::= MINROWS INTEGER */ - -2, /* (83) maxrows ::= MAXROWS INTEGER */ - -2, /* (84) blocks ::= BLOCKS INTEGER */ - -2, /* (85) ctime ::= CTIME INTEGER */ - -2, /* (86) wal ::= WAL INTEGER */ - -2, /* (87) fsync ::= FSYNC INTEGER */ - -2, /* (88) comp ::= COMP INTEGER */ - -2, /* (89) prec ::= PRECISION STRING */ - -2, /* (90) update ::= UPDATE INTEGER */ - -2, /* (91) cachelast ::= CACHELAST INTEGER */ - -2, /* (92) partitions ::= PARTITIONS INTEGER */ - 0, /* (93) db_optr ::= */ - -2, /* (94) db_optr ::= db_optr cache */ - -2, /* (95) db_optr ::= db_optr replica */ - -2, /* (96) db_optr ::= db_optr quorum */ - -2, /* (97) db_optr ::= db_optr days */ - -2, /* (98) db_optr ::= db_optr minrows */ - -2, /* (99) db_optr ::= db_optr maxrows */ - -2, /* (100) db_optr ::= db_optr blocks */ - -2, /* (101) db_optr ::= db_optr ctime */ - -2, /* (102) db_optr ::= db_optr wal */ - -2, /* (103) db_optr ::= db_optr fsync */ - -2, /* (104) db_optr ::= db_optr comp */ - -2, /* (105) db_optr ::= db_optr prec */ - -2, /* (106) db_optr ::= db_optr keep */ - -2, /* (107) db_optr ::= db_optr update */ - -2, /* (108) db_optr ::= db_optr cachelast */ - -1, /* (109) topic_optr ::= db_optr */ - -2, /* (110) topic_optr ::= topic_optr partitions */ - 0, /* (111) alter_db_optr ::= */ - -2, /* (112) alter_db_optr ::= alter_db_optr replica */ - -2, /* (113) alter_db_optr ::= alter_db_optr quorum */ - -2, /* (114) alter_db_optr ::= alter_db_optr keep */ - -2, /* (115) alter_db_optr ::= alter_db_optr blocks */ - -2, /* (116) alter_db_optr ::= alter_db_optr comp */ - -2, /* (117) alter_db_optr ::= alter_db_optr wal */ - -2, /* (118) alter_db_optr ::= alter_db_optr fsync */ - -2, /* (119) alter_db_optr ::= alter_db_optr update */ - -2, /* (120) alter_db_optr ::= alter_db_optr cachelast */ - -1, /* (121) alter_topic_optr ::= alter_db_optr */ - -2, /* (122) alter_topic_optr ::= alter_topic_optr partitions */ - -1, /* (123) typename ::= ids */ - -4, /* (124) typename ::= ids LP signed RP */ - -2, /* (125) typename ::= ids UNSIGNED */ - -1, /* (126) signed ::= INTEGER */ - -2, /* (127) signed ::= PLUS INTEGER */ - -2, /* (128) signed ::= MINUS INTEGER */ - -3, /* (129) cmd ::= CREATE TABLE create_table_args */ - -3, /* (130) cmd ::= CREATE TABLE create_stable_args */ - -3, /* (131) cmd ::= CREATE STABLE create_stable_args */ - -3, /* (132) cmd ::= CREATE TABLE create_table_list */ - -1, /* (133) create_table_list ::= create_from_stable */ - -2, /* (134) create_table_list ::= create_table_list create_from_stable */ - -6, /* (135) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ - -10, /* (136) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ - -10, /* (137) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ - -13, /* (138) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ - -3, /* (139) tagNamelist ::= tagNamelist COMMA ids */ - -1, /* (140) tagNamelist ::= ids */ - -5, /* (141) create_table_args ::= ifnotexists ids cpxName AS select */ - -3, /* (142) columnlist ::= columnlist COMMA column */ - -1, /* (143) columnlist ::= column */ - -2, /* (144) column ::= ids typename */ - -3, /* (145) tagitemlist ::= tagitemlist COMMA tagitem */ - -1, /* (146) tagitemlist ::= tagitem */ - -1, /* (147) tagitem ::= INTEGER */ - -1, /* (148) tagitem ::= FLOAT */ - -1, /* (149) tagitem ::= STRING */ - -1, /* (150) tagitem ::= BOOL */ - -1, /* (151) tagitem ::= NULL */ - -2, /* (152) tagitem ::= MINUS INTEGER */ - -2, /* (153) tagitem ::= MINUS FLOAT */ - -2, /* (154) tagitem ::= PLUS INTEGER */ - -2, /* (155) tagitem ::= PLUS FLOAT */ - -12, /* (156) select ::= SELECT selcollist from where_opt interval_opt fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ - -1, /* (157) union ::= select */ - -3, /* (158) union ::= LP union RP */ - -4, /* (159) union ::= union UNION ALL select */ - -6, /* (160) union ::= union UNION ALL LP select RP */ - -1, /* (161) cmd ::= union */ - -2, /* (162) select ::= SELECT selcollist */ - -2, /* (163) sclp ::= selcollist COMMA */ - 0, /* (164) sclp ::= */ - -4, /* (165) selcollist ::= sclp distinct expr as */ - -2, /* (166) selcollist ::= sclp STAR */ - -2, /* (167) as ::= AS ids */ - -1, /* (168) as ::= ids */ - 0, /* (169) as ::= */ - -1, /* (170) distinct ::= DISTINCT */ - 0, /* (171) distinct ::= */ - -2, /* (172) from ::= FROM tablelist */ - -2, /* (173) tablelist ::= ids cpxName */ - -3, /* (174) tablelist ::= ids cpxName ids */ - -4, /* (175) tablelist ::= tablelist COMMA ids cpxName */ - -5, /* (176) tablelist ::= tablelist COMMA ids cpxName ids */ - -1, /* (177) tmvar ::= VARIABLE */ - -4, /* (178) interval_opt ::= INTERVAL LP tmvar RP */ - -6, /* (179) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ - 0, /* (180) interval_opt ::= */ - 0, /* (181) fill_opt ::= */ - -6, /* (182) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ - -4, /* (183) fill_opt ::= FILL LP ID RP */ - -4, /* (184) sliding_opt ::= SLIDING LP tmvar RP */ - 0, /* (185) sliding_opt ::= */ - 0, /* (186) orderby_opt ::= */ - -3, /* (187) orderby_opt ::= ORDER BY sortlist */ - -4, /* (188) sortlist ::= sortlist COMMA item sortorder */ - -2, /* (189) sortlist ::= item sortorder */ - -2, /* (190) item ::= ids cpxName */ - -1, /* (191) sortorder ::= ASC */ - -1, /* (192) sortorder ::= DESC */ - 0, /* (193) sortorder ::= */ - 0, /* (194) groupby_opt ::= */ - -3, /* (195) groupby_opt ::= GROUP BY grouplist */ - -3, /* (196) grouplist ::= grouplist COMMA item */ - -1, /* (197) grouplist ::= item */ - 0, /* (198) having_opt ::= */ - -2, /* (199) having_opt ::= HAVING expr */ - 0, /* (200) limit_opt ::= */ - -2, /* (201) limit_opt ::= LIMIT signed */ - -4, /* (202) limit_opt ::= LIMIT signed OFFSET signed */ - -4, /* (203) limit_opt ::= LIMIT signed COMMA signed */ - 0, /* (204) slimit_opt ::= */ - -2, /* (205) slimit_opt ::= SLIMIT signed */ - -4, /* (206) slimit_opt ::= SLIMIT signed SOFFSET signed */ - -4, /* (207) slimit_opt ::= SLIMIT signed COMMA signed */ - 0, /* (208) where_opt ::= */ - -2, /* (209) where_opt ::= WHERE expr */ - -3, /* (210) expr ::= LP expr RP */ - -1, /* (211) expr ::= ID */ - -3, /* (212) expr ::= ID DOT ID */ - -3, /* (213) expr ::= ID DOT STAR */ - -1, /* (214) expr ::= INTEGER */ - -2, /* (215) expr ::= MINUS INTEGER */ - -2, /* (216) expr ::= PLUS INTEGER */ - -1, /* (217) expr ::= FLOAT */ - -2, /* (218) expr ::= MINUS FLOAT */ - -2, /* (219) expr ::= PLUS FLOAT */ - -1, /* (220) expr ::= STRING */ - -1, /* (221) expr ::= NOW */ - -1, /* (222) expr ::= VARIABLE */ - -1, /* (223) expr ::= BOOL */ - -4, /* (224) expr ::= ID LP exprlist RP */ - -4, /* (225) expr ::= ID LP STAR RP */ - -3, /* (226) expr ::= expr IS NULL */ - -4, /* (227) expr ::= expr IS NOT NULL */ - -3, /* (228) expr ::= expr LT expr */ - -3, /* (229) expr ::= expr GT expr */ - -3, /* (230) expr ::= expr LE expr */ - -3, /* (231) expr ::= expr GE expr */ - -3, /* (232) expr ::= expr NE expr */ - -3, /* (233) expr ::= expr EQ expr */ - -5, /* (234) expr ::= expr BETWEEN expr AND expr */ - -3, /* (235) expr ::= expr AND expr */ - -3, /* (236) expr ::= expr OR expr */ - -3, /* (237) expr ::= expr PLUS expr */ - -3, /* (238) expr ::= expr MINUS expr */ - -3, /* (239) expr ::= expr STAR expr */ - -3, /* (240) expr ::= expr SLASH expr */ - -3, /* (241) expr ::= expr REM expr */ - -3, /* (242) expr ::= expr LIKE expr */ - -5, /* (243) expr ::= expr IN LP exprlist RP */ - -3, /* (244) exprlist ::= exprlist COMMA expritem */ - -1, /* (245) exprlist ::= expritem */ - -1, /* (246) expritem ::= expr */ - 0, /* (247) expritem ::= */ - -3, /* (248) cmd ::= RESET QUERY CACHE */ - -7, /* (249) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ - -7, /* (250) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ - -7, /* (251) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ - -7, /* (252) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ - -8, /* (253) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ - -9, /* (254) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ - -7, /* (255) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ - -7, /* (256) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ - -7, /* (257) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ - -7, /* (258) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ - -8, /* (259) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ - -3, /* (260) cmd ::= KILL CONNECTION INTEGER */ - -5, /* (261) cmd ::= KILL STREAM INTEGER COLON INTEGER */ - -5, /* (262) cmd ::= KILL QUERY INTEGER COLON INTEGER */ +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ +} yyRuleInfo[] = { + { 188, -1 }, /* (0) program ::= cmd */ + { 189, -2 }, /* (1) cmd ::= SHOW DATABASES */ + { 189, -2 }, /* (2) cmd ::= SHOW TOPICS */ + { 189, -2 }, /* (3) cmd ::= SHOW MNODES */ + { 189, -2 }, /* (4) cmd ::= SHOW DNODES */ + { 189, -2 }, /* (5) cmd ::= SHOW ACCOUNTS */ + { 189, -2 }, /* (6) cmd ::= SHOW USERS */ + { 189, -2 }, /* (7) cmd ::= SHOW MODULES */ + { 189, -2 }, /* (8) cmd ::= SHOW QUERIES */ + { 189, -2 }, /* (9) cmd ::= SHOW CONNECTIONS */ + { 189, -2 }, /* (10) cmd ::= SHOW STREAMS */ + { 189, -2 }, /* (11) cmd ::= SHOW VARIABLES */ + { 189, -2 }, /* (12) cmd ::= SHOW SCORES */ + { 189, -2 }, /* (13) cmd ::= SHOW GRANTS */ + { 189, -2 }, /* (14) cmd ::= SHOW VNODES */ + { 189, -3 }, /* (15) cmd ::= SHOW VNODES IPTOKEN */ + { 190, 0 }, /* (16) dbPrefix ::= */ + { 190, -2 }, /* (17) dbPrefix ::= ids DOT */ + { 192, 0 }, /* (18) cpxName ::= */ + { 192, -2 }, /* (19) cpxName ::= DOT ids */ + { 189, -5 }, /* (20) cmd ::= SHOW CREATE TABLE ids cpxName */ + { 189, -4 }, /* (21) cmd ::= SHOW CREATE DATABASE ids */ + { 189, -3 }, /* (22) cmd ::= SHOW dbPrefix TABLES */ + { 189, -5 }, /* (23) cmd ::= SHOW dbPrefix TABLES LIKE ids */ + { 189, -3 }, /* (24) cmd ::= SHOW dbPrefix STABLES */ + { 189, -5 }, /* (25) cmd ::= SHOW dbPrefix STABLES LIKE ids */ + { 189, -3 }, /* (26) cmd ::= SHOW dbPrefix VGROUPS */ + { 189, -4 }, /* (27) cmd ::= SHOW dbPrefix VGROUPS ids */ + { 189, -5 }, /* (28) cmd ::= DROP TABLE ifexists ids cpxName */ + { 189, -5 }, /* (29) cmd ::= DROP STABLE ifexists ids cpxName */ + { 189, -4 }, /* (30) cmd ::= DROP DATABASE ifexists ids */ + { 189, -4 }, /* (31) cmd ::= DROP TOPIC ifexists ids */ + { 189, -3 }, /* (32) cmd ::= DROP DNODE ids */ + { 189, -3 }, /* (33) cmd ::= DROP USER ids */ + { 189, -3 }, /* (34) cmd ::= DROP ACCOUNT ids */ + { 189, -2 }, /* (35) cmd ::= USE ids */ + { 189, -3 }, /* (36) cmd ::= DESCRIBE ids cpxName */ + { 189, -5 }, /* (37) cmd ::= ALTER USER ids PASS ids */ + { 189, -5 }, /* (38) cmd ::= ALTER USER ids PRIVILEGE ids */ + { 189, -4 }, /* (39) cmd ::= ALTER DNODE ids ids */ + { 189, -5 }, /* (40) cmd ::= ALTER DNODE ids ids ids */ + { 189, -3 }, /* (41) cmd ::= ALTER LOCAL ids */ + { 189, -4 }, /* (42) cmd ::= ALTER LOCAL ids ids */ + { 189, -4 }, /* (43) cmd ::= ALTER DATABASE ids alter_db_optr */ + { 189, -4 }, /* (44) cmd ::= ALTER TOPIC ids alter_topic_optr */ + { 189, -4 }, /* (45) cmd ::= ALTER ACCOUNT ids acct_optr */ + { 189, -6 }, /* (46) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ + { 191, -1 }, /* (47) ids ::= ID */ + { 191, -1 }, /* (48) ids ::= STRING */ + { 193, -2 }, /* (49) ifexists ::= IF EXISTS */ + { 193, 0 }, /* (50) ifexists ::= */ + { 197, -3 }, /* (51) ifnotexists ::= IF NOT EXISTS */ + { 197, 0 }, /* (52) ifnotexists ::= */ + { 189, -3 }, /* (53) cmd ::= CREATE DNODE ids */ + { 189, -6 }, /* (54) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ + { 189, -5 }, /* (55) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + { 189, -5 }, /* (56) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ + { 189, -5 }, /* (57) cmd ::= CREATE USER ids PASS ids */ + { 200, 0 }, /* (58) pps ::= */ + { 200, -2 }, /* (59) pps ::= PPS INTEGER */ + { 201, 0 }, /* (60) tseries ::= */ + { 201, -2 }, /* (61) tseries ::= TSERIES INTEGER */ + { 202, 0 }, /* (62) dbs ::= */ + { 202, -2 }, /* (63) dbs ::= DBS INTEGER */ + { 203, 0 }, /* (64) streams ::= */ + { 203, -2 }, /* (65) streams ::= STREAMS INTEGER */ + { 204, 0 }, /* (66) storage ::= */ + { 204, -2 }, /* (67) storage ::= STORAGE INTEGER */ + { 205, 0 }, /* (68) qtime ::= */ + { 205, -2 }, /* (69) qtime ::= QTIME INTEGER */ + { 206, 0 }, /* (70) users ::= */ + { 206, -2 }, /* (71) users ::= USERS INTEGER */ + { 207, 0 }, /* (72) conns ::= */ + { 207, -2 }, /* (73) conns ::= CONNS INTEGER */ + { 208, 0 }, /* (74) state ::= */ + { 208, -2 }, /* (75) state ::= STATE ids */ + { 196, -9 }, /* (76) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + { 209, -2 }, /* (77) keep ::= KEEP tagitemlist */ + { 211, -2 }, /* (78) cache ::= CACHE INTEGER */ + { 212, -2 }, /* (79) replica ::= REPLICA INTEGER */ + { 213, -2 }, /* (80) quorum ::= QUORUM INTEGER */ + { 214, -2 }, /* (81) days ::= DAYS INTEGER */ + { 215, -2 }, /* (82) minrows ::= MINROWS INTEGER */ + { 216, -2 }, /* (83) maxrows ::= MAXROWS INTEGER */ + { 217, -2 }, /* (84) blocks ::= BLOCKS INTEGER */ + { 218, -2 }, /* (85) ctime ::= CTIME INTEGER */ + { 219, -2 }, /* (86) wal ::= WAL INTEGER */ + { 220, -2 }, /* (87) fsync ::= FSYNC INTEGER */ + { 221, -2 }, /* (88) comp ::= COMP INTEGER */ + { 222, -2 }, /* (89) prec ::= PRECISION STRING */ + { 223, -2 }, /* (90) update ::= UPDATE INTEGER */ + { 224, -2 }, /* (91) cachelast ::= CACHELAST INTEGER */ + { 225, -2 }, /* (92) partitions ::= PARTITIONS INTEGER */ + { 198, 0 }, /* (93) db_optr ::= */ + { 198, -2 }, /* (94) db_optr ::= db_optr cache */ + { 198, -2 }, /* (95) db_optr ::= db_optr replica */ + { 198, -2 }, /* (96) db_optr ::= db_optr quorum */ + { 198, -2 }, /* (97) db_optr ::= db_optr days */ + { 198, -2 }, /* (98) db_optr ::= db_optr minrows */ + { 198, -2 }, /* (99) db_optr ::= db_optr maxrows */ + { 198, -2 }, /* (100) db_optr ::= db_optr blocks */ + { 198, -2 }, /* (101) db_optr ::= db_optr ctime */ + { 198, -2 }, /* (102) db_optr ::= db_optr wal */ + { 198, -2 }, /* (103) db_optr ::= db_optr fsync */ + { 198, -2 }, /* (104) db_optr ::= db_optr comp */ + { 198, -2 }, /* (105) db_optr ::= db_optr prec */ + { 198, -2 }, /* (106) db_optr ::= db_optr keep */ + { 198, -2 }, /* (107) db_optr ::= db_optr update */ + { 198, -2 }, /* (108) db_optr ::= db_optr cachelast */ + { 199, -1 }, /* (109) topic_optr ::= db_optr */ + { 199, -2 }, /* (110) topic_optr ::= topic_optr partitions */ + { 194, 0 }, /* (111) alter_db_optr ::= */ + { 194, -2 }, /* (112) alter_db_optr ::= alter_db_optr replica */ + { 194, -2 }, /* (113) alter_db_optr ::= alter_db_optr quorum */ + { 194, -2 }, /* (114) alter_db_optr ::= alter_db_optr keep */ + { 194, -2 }, /* (115) alter_db_optr ::= alter_db_optr blocks */ + { 194, -2 }, /* (116) alter_db_optr ::= alter_db_optr comp */ + { 194, -2 }, /* (117) alter_db_optr ::= alter_db_optr wal */ + { 194, -2 }, /* (118) alter_db_optr ::= alter_db_optr fsync */ + { 194, -2 }, /* (119) alter_db_optr ::= alter_db_optr update */ + { 194, -2 }, /* (120) alter_db_optr ::= alter_db_optr cachelast */ + { 195, -1 }, /* (121) alter_topic_optr ::= alter_db_optr */ + { 195, -2 }, /* (122) alter_topic_optr ::= alter_topic_optr partitions */ + { 226, -1 }, /* (123) typename ::= ids */ + { 226, -4 }, /* (124) typename ::= ids LP signed RP */ + { 226, -2 }, /* (125) typename ::= ids UNSIGNED */ + { 227, -1 }, /* (126) signed ::= INTEGER */ + { 227, -2 }, /* (127) signed ::= PLUS INTEGER */ + { 227, -2 }, /* (128) signed ::= MINUS INTEGER */ + { 189, -3 }, /* (129) cmd ::= CREATE TABLE create_table_args */ + { 189, -3 }, /* (130) cmd ::= CREATE TABLE create_stable_args */ + { 189, -3 }, /* (131) cmd ::= CREATE STABLE create_stable_args */ + { 189, -3 }, /* (132) cmd ::= CREATE TABLE create_table_list */ + { 230, -1 }, /* (133) create_table_list ::= create_from_stable */ + { 230, -2 }, /* (134) create_table_list ::= create_table_list create_from_stable */ + { 228, -6 }, /* (135) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + { 229, -10 }, /* (136) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + { 231, -10 }, /* (137) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + { 231, -13 }, /* (138) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + { 233, -3 }, /* (139) tagNamelist ::= tagNamelist COMMA ids */ + { 233, -1 }, /* (140) tagNamelist ::= ids */ + { 228, -5 }, /* (141) create_table_args ::= ifnotexists ids cpxName AS select */ + { 232, -3 }, /* (142) columnlist ::= columnlist COMMA column */ + { 232, -1 }, /* (143) columnlist ::= column */ + { 235, -2 }, /* (144) column ::= ids typename */ + { 210, -3 }, /* (145) tagitemlist ::= tagitemlist COMMA tagitem */ + { 210, -1 }, /* (146) tagitemlist ::= tagitem */ + { 236, -1 }, /* (147) tagitem ::= INTEGER */ + { 236, -1 }, /* (148) tagitem ::= FLOAT */ + { 236, -1 }, /* (149) tagitem ::= STRING */ + { 236, -1 }, /* (150) tagitem ::= BOOL */ + { 236, -1 }, /* (151) tagitem ::= NULL */ + { 236, -2 }, /* (152) tagitem ::= MINUS INTEGER */ + { 236, -2 }, /* (153) tagitem ::= MINUS FLOAT */ + { 236, -2 }, /* (154) tagitem ::= PLUS INTEGER */ + { 236, -2 }, /* (155) tagitem ::= PLUS FLOAT */ + { 234, -12 }, /* (156) select ::= SELECT selcollist from where_opt interval_opt fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ + { 248, -1 }, /* (157) union ::= select */ + { 248, -3 }, /* (158) union ::= LP union RP */ + { 248, -4 }, /* (159) union ::= union UNION ALL select */ + { 248, -6 }, /* (160) union ::= union UNION ALL LP select RP */ + { 189, -1 }, /* (161) cmd ::= union */ + { 234, -2 }, /* (162) select ::= SELECT selcollist */ + { 249, -2 }, /* (163) sclp ::= selcollist COMMA */ + { 249, 0 }, /* (164) sclp ::= */ + { 237, -4 }, /* (165) selcollist ::= sclp distinct expr as */ + { 237, -2 }, /* (166) selcollist ::= sclp STAR */ + { 252, -2 }, /* (167) as ::= AS ids */ + { 252, -1 }, /* (168) as ::= ids */ + { 252, 0 }, /* (169) as ::= */ + { 250, -1 }, /* (170) distinct ::= DISTINCT */ + { 250, 0 }, /* (171) distinct ::= */ + { 238, -2 }, /* (172) from ::= FROM tablelist */ + { 253, -2 }, /* (173) tablelist ::= ids cpxName */ + { 253, -3 }, /* (174) tablelist ::= ids cpxName ids */ + { 253, -4 }, /* (175) tablelist ::= tablelist COMMA ids cpxName */ + { 253, -5 }, /* (176) tablelist ::= tablelist COMMA ids cpxName ids */ + { 254, -1 }, /* (177) tmvar ::= VARIABLE */ + { 240, -4 }, /* (178) interval_opt ::= INTERVAL LP tmvar RP */ + { 240, -6 }, /* (179) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ + { 240, 0 }, /* (180) interval_opt ::= */ + { 241, 0 }, /* (181) fill_opt ::= */ + { 241, -6 }, /* (182) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + { 241, -4 }, /* (183) fill_opt ::= FILL LP ID RP */ + { 242, -4 }, /* (184) sliding_opt ::= SLIDING LP tmvar RP */ + { 242, 0 }, /* (185) sliding_opt ::= */ + { 244, 0 }, /* (186) orderby_opt ::= */ + { 244, -3 }, /* (187) orderby_opt ::= ORDER BY sortlist */ + { 255, -4 }, /* (188) sortlist ::= sortlist COMMA item sortorder */ + { 255, -2 }, /* (189) sortlist ::= item sortorder */ + { 257, -2 }, /* (190) item ::= ids cpxName */ + { 258, -1 }, /* (191) sortorder ::= ASC */ + { 258, -1 }, /* (192) sortorder ::= DESC */ + { 258, 0 }, /* (193) sortorder ::= */ + { 243, 0 }, /* (194) groupby_opt ::= */ + { 243, -3 }, /* (195) groupby_opt ::= GROUP BY grouplist */ + { 259, -3 }, /* (196) grouplist ::= grouplist COMMA item */ + { 259, -1 }, /* (197) grouplist ::= item */ + { 245, 0 }, /* (198) having_opt ::= */ + { 245, -2 }, /* (199) having_opt ::= HAVING expr */ + { 247, 0 }, /* (200) limit_opt ::= */ + { 247, -2 }, /* (201) limit_opt ::= LIMIT signed */ + { 247, -4 }, /* (202) limit_opt ::= LIMIT signed OFFSET signed */ + { 247, -4 }, /* (203) limit_opt ::= LIMIT signed COMMA signed */ + { 246, 0 }, /* (204) slimit_opt ::= */ + { 246, -2 }, /* (205) slimit_opt ::= SLIMIT signed */ + { 246, -4 }, /* (206) slimit_opt ::= SLIMIT signed SOFFSET signed */ + { 246, -4 }, /* (207) slimit_opt ::= SLIMIT signed COMMA signed */ + { 239, 0 }, /* (208) where_opt ::= */ + { 239, -2 }, /* (209) where_opt ::= WHERE expr */ + { 251, -3 }, /* (210) expr ::= LP expr RP */ + { 251, -1 }, /* (211) expr ::= ID */ + { 251, -3 }, /* (212) expr ::= ID DOT ID */ + { 251, -3 }, /* (213) expr ::= ID DOT STAR */ + { 251, -1 }, /* (214) expr ::= INTEGER */ + { 251, -2 }, /* (215) expr ::= MINUS INTEGER */ + { 251, -2 }, /* (216) expr ::= PLUS INTEGER */ + { 251, -1 }, /* (217) expr ::= FLOAT */ + { 251, -2 }, /* (218) expr ::= MINUS FLOAT */ + { 251, -2 }, /* (219) expr ::= PLUS FLOAT */ + { 251, -1 }, /* (220) expr ::= STRING */ + { 251, -1 }, /* (221) expr ::= NOW */ + { 251, -1 }, /* (222) expr ::= VARIABLE */ + { 251, -1 }, /* (223) expr ::= BOOL */ + { 251, -4 }, /* (224) expr ::= ID LP exprlist RP */ + { 251, -4 }, /* (225) expr ::= ID LP STAR RP */ + { 251, -3 }, /* (226) expr ::= expr IS NULL */ + { 251, -4 }, /* (227) expr ::= expr IS NOT NULL */ + { 251, -3 }, /* (228) expr ::= expr LT expr */ + { 251, -3 }, /* (229) expr ::= expr GT expr */ + { 251, -3 }, /* (230) expr ::= expr LE expr */ + { 251, -3 }, /* (231) expr ::= expr GE expr */ + { 251, -3 }, /* (232) expr ::= expr NE expr */ + { 251, -3 }, /* (233) expr ::= expr EQ expr */ + { 251, -5 }, /* (234) expr ::= expr BETWEEN expr AND expr */ + { 251, -3 }, /* (235) expr ::= expr AND expr */ + { 251, -3 }, /* (236) expr ::= expr OR expr */ + { 251, -3 }, /* (237) expr ::= expr PLUS expr */ + { 251, -3 }, /* (238) expr ::= expr MINUS expr */ + { 251, -3 }, /* (239) expr ::= expr STAR expr */ + { 251, -3 }, /* (240) expr ::= expr SLASH expr */ + { 251, -3 }, /* (241) expr ::= expr REM expr */ + { 251, -3 }, /* (242) expr ::= expr LIKE expr */ + { 251, -5 }, /* (243) expr ::= expr IN LP exprlist RP */ + { 260, -3 }, /* (244) exprlist ::= exprlist COMMA expritem */ + { 260, -1 }, /* (245) exprlist ::= expritem */ + { 261, -1 }, /* (246) expritem ::= expr */ + { 261, 0 }, /* (247) expritem ::= */ + { 189, -3 }, /* (248) cmd ::= RESET QUERY CACHE */ + { 189, -7 }, /* (249) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + { 189, -7 }, /* (250) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + { 189, -7 }, /* (251) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + { 189, -7 }, /* (252) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + { 189, -8 }, /* (253) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + { 189, -9 }, /* (254) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + { 189, -7 }, /* (255) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + { 189, -7 }, /* (256) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + { 189, -7 }, /* (257) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + { 189, -7 }, /* (258) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + { 189, -8 }, /* (259) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + { 189, -3 }, /* (260) cmd ::= KILL CONNECTION INTEGER */ + { 189, -5 }, /* (261) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + { 189, -5 }, /* (262) cmd ::= KILL QUERY INTEGER COLON INTEGER */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -2346,34 +2012,30 @@ static void yy_accept(yyParser*); /* Forward Declaration */ ** only called from one place, optimizing compilers will in-line it, which ** means that the extra parameters have no performance impact. */ -static YYACTIONTYPE yy_reduce( +static void yy_reduce( yyParser *yypParser, /* The parser */ unsigned int yyruleno, /* Number of the rule by which to reduce */ int yyLookahead, /* Lookahead token, or YYNOCODE if none */ ParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ - ParseCTX_PDECL /* %extra_context */ ){ int yygoto; /* The next state */ - YYACTIONTYPE yyact; /* The next action */ + int yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ - ParseARG_FETCH + ParseARG_FETCH; (void)yyLookahead; (void)yyLookaheadToken; yymsp = yypParser->yytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfoNRhs[yyruleno]; + yysize = yyRuleInfo[yyruleno].nrhs; if( yysize ){ - fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", + fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", yyTracePrompt, - yyruleno, yyRuleName[yyruleno], - yyrulenoyytos - yypParser->yystack)>yypParser->yyhwm ){ yypParser->yyhwm++; @@ -2391,19 +2053,13 @@ static YYACTIONTYPE yy_reduce( #if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); - /* The call to yyStackOverflow() above pops the stack until it is - ** empty, causing the main parser loop to exit. So the return value - ** is never used and does not matter. */ - return 0; + return; } #else if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); - /* The call to yyStackOverflow() above pops the stack until it is - ** empty, causing the main parser loop to exit. So the return value - ** is never used and does not matter. */ - return 0; + return; } yymsp = yypParser->yytos; } @@ -2588,13 +2244,13 @@ static YYACTIONTYPE yy_reduce( break; case 43: /* cmd ::= ALTER DATABASE ids alter_db_optr */ case 44: /* cmd ::= ALTER TOPIC ids alter_topic_optr */ yytestcase(yyruleno==44); -{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy100, &t);} +{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy94, &t);} break; case 45: /* cmd ::= ALTER ACCOUNT ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy505);} +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy419);} break; case 46: /* cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy505);} +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy419);} break; case 47: /* ids ::= ID */ case 48: /* ids ::= STRING */ yytestcase(yyruleno==48); @@ -2616,11 +2272,11 @@ static YYACTIONTYPE yy_reduce( { setDCLSQLElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &yymsp[0].minor.yy0);} break; case 54: /* cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy505);} +{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy419);} break; case 55: /* cmd ::= CREATE DATABASE ifnotexists ids db_optr */ case 56: /* cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ yytestcase(yyruleno==56); -{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy100, &yymsp[-2].minor.yy0);} +{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy94, &yymsp[-2].minor.yy0);} break; case 57: /* cmd ::= CREATE USER ids PASS ids */ { setCreateUserSql(pInfo, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);} @@ -2649,20 +2305,20 @@ static YYACTIONTYPE yy_reduce( break; case 76: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ { - yylhsminor.yy505.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; - yylhsminor.yy505.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; - yylhsminor.yy505.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; - yylhsminor.yy505.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; - yylhsminor.yy505.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; - yylhsminor.yy505.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy505.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy505.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; - yylhsminor.yy505.stat = yymsp[0].minor.yy0; -} - yymsp[-8].minor.yy505 = yylhsminor.yy505; + yylhsminor.yy419.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; + yylhsminor.yy419.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; + yylhsminor.yy419.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; + yylhsminor.yy419.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; + yylhsminor.yy419.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; + yylhsminor.yy419.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy419.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy419.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; + yylhsminor.yy419.stat = yymsp[0].minor.yy0; +} + yymsp[-8].minor.yy419 = yylhsminor.yy419; break; case 77: /* keep ::= KEEP tagitemlist */ -{ yymsp[-1].minor.yy207 = yymsp[0].minor.yy207; } +{ yymsp[-1].minor.yy429 = yymsp[0].minor.yy429; } break; case 78: /* cache ::= CACHE INTEGER */ case 79: /* replica ::= REPLICA INTEGER */ yytestcase(yyruleno==79); @@ -2682,234 +2338,234 @@ static YYACTIONTYPE yy_reduce( { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } break; case 93: /* db_optr ::= */ -{setDefaultCreateDbOption(&yymsp[1].minor.yy100); yymsp[1].minor.yy100.dbType = TSDB_DB_TYPE_DEFAULT;} +{setDefaultCreateDbOption(&yymsp[1].minor.yy94); yymsp[1].minor.yy94.dbType = TSDB_DB_TYPE_DEFAULT;} break; case 94: /* db_optr ::= db_optr cache */ -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 95: /* db_optr ::= db_optr replica */ case 112: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==112); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 96: /* db_optr ::= db_optr quorum */ case 113: /* alter_db_optr ::= alter_db_optr quorum */ yytestcase(yyruleno==113); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 97: /* db_optr ::= db_optr days */ -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 98: /* db_optr ::= db_optr minrows */ -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 99: /* db_optr ::= db_optr maxrows */ -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 100: /* db_optr ::= db_optr blocks */ case 115: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==115); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 101: /* db_optr ::= db_optr ctime */ -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 102: /* db_optr ::= db_optr wal */ case 117: /* alter_db_optr ::= alter_db_optr wal */ yytestcase(yyruleno==117); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 103: /* db_optr ::= db_optr fsync */ case 118: /* alter_db_optr ::= alter_db_optr fsync */ yytestcase(yyruleno==118); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 104: /* db_optr ::= db_optr comp */ case 116: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==116); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 105: /* db_optr ::= db_optr prec */ -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.precision = yymsp[0].minor.yy0; } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.precision = yymsp[0].minor.yy0; } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 106: /* db_optr ::= db_optr keep */ case 114: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==114); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.keep = yymsp[0].minor.yy207; } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.keep = yymsp[0].minor.yy429; } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 107: /* db_optr ::= db_optr update */ case 119: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==119); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 108: /* db_optr ::= db_optr cachelast */ case 120: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==120); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 109: /* topic_optr ::= db_optr */ case 121: /* alter_topic_optr ::= alter_db_optr */ yytestcase(yyruleno==121); -{ yylhsminor.yy100 = yymsp[0].minor.yy100; yylhsminor.yy100.dbType = TSDB_DB_TYPE_TOPIC; } - yymsp[0].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[0].minor.yy94; yylhsminor.yy94.dbType = TSDB_DB_TYPE_TOPIC; } + yymsp[0].minor.yy94 = yylhsminor.yy94; break; case 110: /* topic_optr ::= topic_optr partitions */ case 122: /* alter_topic_optr ::= alter_topic_optr partitions */ yytestcase(yyruleno==122); -{ yylhsminor.yy100 = yymsp[-1].minor.yy100; yylhsminor.yy100.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy100 = yylhsminor.yy100; +{ yylhsminor.yy94 = yymsp[-1].minor.yy94; yylhsminor.yy94.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy94 = yylhsminor.yy94; break; case 111: /* alter_db_optr ::= */ -{ setDefaultCreateDbOption(&yymsp[1].minor.yy100); yymsp[1].minor.yy100.dbType = TSDB_DB_TYPE_DEFAULT;} +{ setDefaultCreateDbOption(&yymsp[1].minor.yy94); yymsp[1].minor.yy94.dbType = TSDB_DB_TYPE_DEFAULT;} break; case 123: /* typename ::= ids */ { yymsp[0].minor.yy0.type = 0; - tSqlSetColumnType (&yylhsminor.yy517, &yymsp[0].minor.yy0); + tSqlSetColumnType (&yylhsminor.yy451, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy517 = yylhsminor.yy517; + yymsp[0].minor.yy451 = yylhsminor.yy451; break; case 124: /* typename ::= ids LP signed RP */ { - if (yymsp[-1].minor.yy208 <= 0) { + if (yymsp[-1].minor.yy481 <= 0) { yymsp[-3].minor.yy0.type = 0; - tSqlSetColumnType(&yylhsminor.yy517, &yymsp[-3].minor.yy0); + tSqlSetColumnType(&yylhsminor.yy451, &yymsp[-3].minor.yy0); } else { - yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy208; // negative value of name length - tSqlSetColumnType(&yylhsminor.yy517, &yymsp[-3].minor.yy0); + yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy481; // negative value of name length + tSqlSetColumnType(&yylhsminor.yy451, &yymsp[-3].minor.yy0); } } - yymsp[-3].minor.yy517 = yylhsminor.yy517; + yymsp[-3].minor.yy451 = yylhsminor.yy451; break; case 125: /* typename ::= ids UNSIGNED */ { yymsp[-1].minor.yy0.type = 0; yymsp[-1].minor.yy0.n = ((yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z); - tSqlSetColumnType (&yylhsminor.yy517, &yymsp[-1].minor.yy0); + tSqlSetColumnType (&yylhsminor.yy451, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy517 = yylhsminor.yy517; + yymsp[-1].minor.yy451 = yylhsminor.yy451; break; case 126: /* signed ::= INTEGER */ -{ yylhsminor.yy208 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[0].minor.yy208 = yylhsminor.yy208; +{ yylhsminor.yy481 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[0].minor.yy481 = yylhsminor.yy481; break; case 127: /* signed ::= PLUS INTEGER */ -{ yymsp[-1].minor.yy208 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +{ yymsp[-1].minor.yy481 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } break; case 128: /* signed ::= MINUS INTEGER */ -{ yymsp[-1].minor.yy208 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} +{ yymsp[-1].minor.yy481 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} break; case 132: /* cmd ::= CREATE TABLE create_table_list */ -{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy414;} +{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy310;} break; case 133: /* create_table_list ::= create_from_stable */ { SCreateTableSQL* pCreateTable = calloc(1, sizeof(SCreateTableSQL)); pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); - taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy542); + taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy252); pCreateTable->type = TSQL_CREATE_TABLE_FROM_STABLE; - yylhsminor.yy414 = pCreateTable; + yylhsminor.yy310 = pCreateTable; } - yymsp[0].minor.yy414 = yylhsminor.yy414; + yymsp[0].minor.yy310 = yylhsminor.yy310; break; case 134: /* create_table_list ::= create_table_list create_from_stable */ { - taosArrayPush(yymsp[-1].minor.yy414->childTableInfo, &yymsp[0].minor.yy542); - yylhsminor.yy414 = yymsp[-1].minor.yy414; + taosArrayPush(yymsp[-1].minor.yy310->childTableInfo, &yymsp[0].minor.yy252); + yylhsminor.yy310 = yymsp[-1].minor.yy310; } - yymsp[-1].minor.yy414 = yylhsminor.yy414; + yymsp[-1].minor.yy310 = yylhsminor.yy310; break; case 135: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ { - yylhsminor.yy414 = tSetCreateSqlElems(yymsp[-1].minor.yy207, NULL, NULL, TSQL_CREATE_TABLE); - setSqlInfo(pInfo, yylhsminor.yy414, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy310 = tSetCreateSqlElems(yymsp[-1].minor.yy429, NULL, NULL, TSQL_CREATE_TABLE); + setSqlInfo(pInfo, yylhsminor.yy310, NULL, TSDB_SQL_CREATE_TABLE); yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; setCreatedTableName(pInfo, &yymsp[-4].minor.yy0, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy414 = yylhsminor.yy414; + yymsp[-5].minor.yy310 = yylhsminor.yy310; break; case 136: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ { - yylhsminor.yy414 = tSetCreateSqlElems(yymsp[-5].minor.yy207, yymsp[-1].minor.yy207, NULL, TSQL_CREATE_STABLE); - setSqlInfo(pInfo, yylhsminor.yy414, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy310 = tSetCreateSqlElems(yymsp[-5].minor.yy429, yymsp[-1].minor.yy429, NULL, TSQL_CREATE_STABLE); + setSqlInfo(pInfo, yylhsminor.yy310, NULL, TSDB_SQL_CREATE_TABLE); yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; setCreatedTableName(pInfo, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); } - yymsp[-9].minor.yy414 = yylhsminor.yy414; + yymsp[-9].minor.yy310 = yylhsminor.yy310; break; case 137: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - yylhsminor.yy542 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy207, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); + yylhsminor.yy252 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy429, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); } - yymsp[-9].minor.yy542 = yylhsminor.yy542; + yymsp[-9].minor.yy252 = yylhsminor.yy252; break; case 138: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ { yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; yymsp[-11].minor.yy0.n += yymsp[-10].minor.yy0.n; - yylhsminor.yy542 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy207, yymsp[-1].minor.yy207, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); + yylhsminor.yy252 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy429, yymsp[-1].minor.yy429, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); } - yymsp[-12].minor.yy542 = yylhsminor.yy542; + yymsp[-12].minor.yy252 = yylhsminor.yy252; break; case 139: /* tagNamelist ::= tagNamelist COMMA ids */ -{taosArrayPush(yymsp[-2].minor.yy207, &yymsp[0].minor.yy0); yylhsminor.yy207 = yymsp[-2].minor.yy207; } - yymsp[-2].minor.yy207 = yylhsminor.yy207; +{taosArrayPush(yymsp[-2].minor.yy429, &yymsp[0].minor.yy0); yylhsminor.yy429 = yymsp[-2].minor.yy429; } + yymsp[-2].minor.yy429 = yylhsminor.yy429; break; case 140: /* tagNamelist ::= ids */ -{yylhsminor.yy207 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy207, &yymsp[0].minor.yy0);} - yymsp[0].minor.yy207 = yylhsminor.yy207; +{yylhsminor.yy429 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy429, &yymsp[0].minor.yy0);} + yymsp[0].minor.yy429 = yylhsminor.yy429; break; case 141: /* create_table_args ::= ifnotexists ids cpxName AS select */ { - yylhsminor.yy414 = tSetCreateSqlElems(NULL, NULL, yymsp[0].minor.yy526, TSQL_CREATE_STREAM); - setSqlInfo(pInfo, yylhsminor.yy414, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy310 = tSetCreateSqlElems(NULL, NULL, yymsp[0].minor.yy372, TSQL_CREATE_STREAM); + setSqlInfo(pInfo, yylhsminor.yy310, NULL, TSDB_SQL_CREATE_TABLE); yymsp[-3].minor.yy0.n += yymsp[-2].minor.yy0.n; setCreatedTableName(pInfo, &yymsp[-3].minor.yy0, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy414 = yylhsminor.yy414; + yymsp[-4].minor.yy310 = yylhsminor.yy310; break; case 142: /* columnlist ::= columnlist COMMA column */ -{taosArrayPush(yymsp[-2].minor.yy207, &yymsp[0].minor.yy517); yylhsminor.yy207 = yymsp[-2].minor.yy207; } - yymsp[-2].minor.yy207 = yylhsminor.yy207; +{taosArrayPush(yymsp[-2].minor.yy429, &yymsp[0].minor.yy451); yylhsminor.yy429 = yymsp[-2].minor.yy429; } + yymsp[-2].minor.yy429 = yylhsminor.yy429; break; case 143: /* columnlist ::= column */ -{yylhsminor.yy207 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy207, &yymsp[0].minor.yy517);} - yymsp[0].minor.yy207 = yylhsminor.yy207; +{yylhsminor.yy429 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy429, &yymsp[0].minor.yy451);} + yymsp[0].minor.yy429 = yylhsminor.yy429; break; case 144: /* column ::= ids typename */ { - tSqlSetColumnInfo(&yylhsminor.yy517, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy517); + tSqlSetColumnInfo(&yylhsminor.yy451, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy451); } - yymsp[-1].minor.yy517 = yylhsminor.yy517; + yymsp[-1].minor.yy451 = yylhsminor.yy451; break; case 145: /* tagitemlist ::= tagitemlist COMMA tagitem */ -{ yylhsminor.yy207 = tVariantListAppend(yymsp[-2].minor.yy207, &yymsp[0].minor.yy232, -1); } - yymsp[-2].minor.yy207 = yylhsminor.yy207; +{ yylhsminor.yy429 = tVariantListAppend(yymsp[-2].minor.yy429, &yymsp[0].minor.yy218, -1); } + yymsp[-2].minor.yy429 = yylhsminor.yy429; break; case 146: /* tagitemlist ::= tagitem */ -{ yylhsminor.yy207 = tVariantListAppend(NULL, &yymsp[0].minor.yy232, -1); } - yymsp[0].minor.yy207 = yylhsminor.yy207; +{ yylhsminor.yy429 = tVariantListAppend(NULL, &yymsp[0].minor.yy218, -1); } + yymsp[0].minor.yy429 = yylhsminor.yy429; break; case 147: /* tagitem ::= INTEGER */ case 148: /* tagitem ::= FLOAT */ yytestcase(yyruleno==148); case 149: /* tagitem ::= STRING */ yytestcase(yyruleno==149); case 150: /* tagitem ::= BOOL */ yytestcase(yyruleno==150); -{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy232, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy232 = yylhsminor.yy232; +{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy218, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy218 = yylhsminor.yy218; break; case 151: /* tagitem ::= NULL */ -{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy232, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy232 = yylhsminor.yy232; +{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy218, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy218 = yylhsminor.yy218; break; case 152: /* tagitem ::= MINUS INTEGER */ case 153: /* tagitem ::= MINUS FLOAT */ yytestcase(yyruleno==153); @@ -2919,59 +2575,59 @@ static YYACTIONTYPE yy_reduce( yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = yymsp[0].minor.yy0.type; toTSDBType(yymsp[-1].minor.yy0.type); - tVariantCreate(&yylhsminor.yy232, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy218, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy232 = yylhsminor.yy232; + yymsp[-1].minor.yy218 = yylhsminor.yy218; break; case 156: /* select ::= SELECT selcollist from where_opt interval_opt fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ { - yylhsminor.yy526 = tSetQuerySqlElems(&yymsp[-11].minor.yy0, yymsp[-10].minor.yy178, yymsp[-9].minor.yy207, yymsp[-8].minor.yy484, yymsp[-4].minor.yy207, yymsp[-3].minor.yy207, &yymsp[-7].minor.yy126, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy207, &yymsp[0].minor.yy314, &yymsp[-1].minor.yy314); + yylhsminor.yy372 = tSetQuerySqlElems(&yymsp[-11].minor.yy0, yymsp[-10].minor.yy170, yymsp[-9].minor.yy429, yymsp[-8].minor.yy282, yymsp[-4].minor.yy429, yymsp[-3].minor.yy429, &yymsp[-7].minor.yy220, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy429, &yymsp[0].minor.yy18, &yymsp[-1].minor.yy18); } - yymsp[-11].minor.yy526 = yylhsminor.yy526; + yymsp[-11].minor.yy372 = yylhsminor.yy372; break; case 157: /* union ::= select */ -{ yylhsminor.yy441 = setSubclause(NULL, yymsp[0].minor.yy526); } - yymsp[0].minor.yy441 = yylhsminor.yy441; +{ yylhsminor.yy141 = setSubclause(NULL, yymsp[0].minor.yy372); } + yymsp[0].minor.yy141 = yylhsminor.yy141; break; case 158: /* union ::= LP union RP */ -{ yymsp[-2].minor.yy441 = yymsp[-1].minor.yy441; } +{ yymsp[-2].minor.yy141 = yymsp[-1].minor.yy141; } break; case 159: /* union ::= union UNION ALL select */ -{ yylhsminor.yy441 = appendSelectClause(yymsp[-3].minor.yy441, yymsp[0].minor.yy526); } - yymsp[-3].minor.yy441 = yylhsminor.yy441; +{ yylhsminor.yy141 = appendSelectClause(yymsp[-3].minor.yy141, yymsp[0].minor.yy372); } + yymsp[-3].minor.yy141 = yylhsminor.yy141; break; case 160: /* union ::= union UNION ALL LP select RP */ -{ yylhsminor.yy441 = appendSelectClause(yymsp[-5].minor.yy441, yymsp[-1].minor.yy526); } - yymsp[-5].minor.yy441 = yylhsminor.yy441; +{ yylhsminor.yy141 = appendSelectClause(yymsp[-5].minor.yy141, yymsp[-1].minor.yy372); } + yymsp[-5].minor.yy141 = yylhsminor.yy141; break; case 161: /* cmd ::= union */ -{ setSqlInfo(pInfo, yymsp[0].minor.yy441, NULL, TSDB_SQL_SELECT); } +{ setSqlInfo(pInfo, yymsp[0].minor.yy141, NULL, TSDB_SQL_SELECT); } break; case 162: /* select ::= SELECT selcollist */ { - yylhsminor.yy526 = tSetQuerySqlElems(&yymsp[-1].minor.yy0, yymsp[0].minor.yy178, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + yylhsminor.yy372 = tSetQuerySqlElems(&yymsp[-1].minor.yy0, yymsp[0].minor.yy170, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } - yymsp[-1].minor.yy526 = yylhsminor.yy526; + yymsp[-1].minor.yy372 = yylhsminor.yy372; break; case 163: /* sclp ::= selcollist COMMA */ -{yylhsminor.yy178 = yymsp[-1].minor.yy178;} - yymsp[-1].minor.yy178 = yylhsminor.yy178; +{yylhsminor.yy170 = yymsp[-1].minor.yy170;} + yymsp[-1].minor.yy170 = yylhsminor.yy170; break; case 164: /* sclp ::= */ -{yymsp[1].minor.yy178 = 0;} +{yymsp[1].minor.yy170 = 0;} break; case 165: /* selcollist ::= sclp distinct expr as */ { - yylhsminor.yy178 = tSqlExprListAppend(yymsp[-3].minor.yy178, yymsp[-1].minor.yy484, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); + yylhsminor.yy170 = tSqlExprListAppend(yymsp[-3].minor.yy170, yymsp[-1].minor.yy282, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); } - yymsp[-3].minor.yy178 = yylhsminor.yy178; + yymsp[-3].minor.yy170 = yylhsminor.yy170; break; case 166: /* selcollist ::= sclp STAR */ { tSQLExpr *pNode = tSqlExprIdValueCreate(NULL, TK_ALL); - yylhsminor.yy178 = tSqlExprListAppend(yymsp[-1].minor.yy178, pNode, 0, 0); + yylhsminor.yy170 = tSqlExprListAppend(yymsp[-1].minor.yy170, pNode, 0, 0); } - yymsp[-1].minor.yy178 = yylhsminor.yy178; + yymsp[-1].minor.yy170 = yylhsminor.yy170; break; case 167: /* as ::= AS ids */ { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } @@ -2988,61 +2644,61 @@ static YYACTIONTYPE yy_reduce( yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 172: /* from ::= FROM tablelist */ -{yymsp[-1].minor.yy207 = yymsp[0].minor.yy207;} +{yymsp[-1].minor.yy429 = yymsp[0].minor.yy429;} break; case 173: /* tablelist ::= ids cpxName */ { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy207 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); - yylhsminor.yy207 = tVariantListAppendToken(yylhsminor.yy207, &yymsp[-1].minor.yy0, -1); // table alias name + yylhsminor.yy429 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(yylhsminor.yy429, &yymsp[-1].minor.yy0, -1); // table alias name } - yymsp[-1].minor.yy207 = yylhsminor.yy207; + yymsp[-1].minor.yy429 = yylhsminor.yy429; break; case 174: /* tablelist ::= ids cpxName ids */ { toTSDBType(yymsp[-2].minor.yy0.type); toTSDBType(yymsp[0].minor.yy0.type); yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy207 = tVariantListAppendToken(NULL, &yymsp[-2].minor.yy0, -1); - yylhsminor.yy207 = tVariantListAppendToken(yylhsminor.yy207, &yymsp[0].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(NULL, &yymsp[-2].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(yylhsminor.yy429, &yymsp[0].minor.yy0, -1); } - yymsp[-2].minor.yy207 = yylhsminor.yy207; + yymsp[-2].minor.yy429 = yylhsminor.yy429; break; case 175: /* tablelist ::= tablelist COMMA ids cpxName */ { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy207 = tVariantListAppendToken(yymsp[-3].minor.yy207, &yymsp[-1].minor.yy0, -1); - yylhsminor.yy207 = tVariantListAppendToken(yylhsminor.yy207, &yymsp[-1].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(yymsp[-3].minor.yy429, &yymsp[-1].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(yylhsminor.yy429, &yymsp[-1].minor.yy0, -1); } - yymsp[-3].minor.yy207 = yylhsminor.yy207; + yymsp[-3].minor.yy429 = yylhsminor.yy429; break; case 176: /* tablelist ::= tablelist COMMA ids cpxName ids */ { toTSDBType(yymsp[-2].minor.yy0.type); toTSDBType(yymsp[0].minor.yy0.type); yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy207 = tVariantListAppendToken(yymsp[-4].minor.yy207, &yymsp[-2].minor.yy0, -1); - yylhsminor.yy207 = tVariantListAppendToken(yylhsminor.yy207, &yymsp[0].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(yymsp[-4].minor.yy429, &yymsp[-2].minor.yy0, -1); + yylhsminor.yy429 = tVariantListAppendToken(yylhsminor.yy429, &yymsp[0].minor.yy0, -1); } - yymsp[-4].minor.yy207 = yylhsminor.yy207; + yymsp[-4].minor.yy429 = yylhsminor.yy429; break; case 177: /* tmvar ::= VARIABLE */ {yylhsminor.yy0 = yymsp[0].minor.yy0;} yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 178: /* interval_opt ::= INTERVAL LP tmvar RP */ -{yymsp[-3].minor.yy126.interval = yymsp[-1].minor.yy0; yymsp[-3].minor.yy126.offset.n = 0; yymsp[-3].minor.yy126.offset.z = NULL; yymsp[-3].minor.yy126.offset.type = 0;} +{yymsp[-3].minor.yy220.interval = yymsp[-1].minor.yy0; yymsp[-3].minor.yy220.offset.n = 0; yymsp[-3].minor.yy220.offset.z = NULL; yymsp[-3].minor.yy220.offset.type = 0;} break; case 179: /* interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ -{yymsp[-5].minor.yy126.interval = yymsp[-3].minor.yy0; yymsp[-5].minor.yy126.offset = yymsp[-1].minor.yy0;} +{yymsp[-5].minor.yy220.interval = yymsp[-3].minor.yy0; yymsp[-5].minor.yy220.offset = yymsp[-1].minor.yy0;} break; case 180: /* interval_opt ::= */ -{memset(&yymsp[1].minor.yy126, 0, sizeof(yymsp[1].minor.yy126));} +{memset(&yymsp[1].minor.yy220, 0, sizeof(yymsp[1].minor.yy220));} break; case 181: /* fill_opt ::= */ -{yymsp[1].minor.yy207 = 0; } +{yymsp[1].minor.yy429 = 0; } break; case 182: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ { @@ -3050,14 +2706,14 @@ static YYACTIONTYPE yy_reduce( toTSDBType(yymsp[-3].minor.yy0.type); tVariantCreate(&A, &yymsp[-3].minor.yy0); - tVariantListInsert(yymsp[-1].minor.yy207, &A, -1, 0); - yymsp[-5].minor.yy207 = yymsp[-1].minor.yy207; + tVariantListInsert(yymsp[-1].minor.yy429, &A, -1, 0); + yymsp[-5].minor.yy429 = yymsp[-1].minor.yy429; } break; case 183: /* fill_opt ::= FILL LP ID RP */ { toTSDBType(yymsp[-1].minor.yy0.type); - yymsp[-3].minor.yy207 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); + yymsp[-3].minor.yy429 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); } break; case 184: /* sliding_opt ::= SLIDING LP tmvar RP */ @@ -3067,31 +2723,31 @@ static YYACTIONTYPE yy_reduce( {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = NULL; yymsp[1].minor.yy0.type = 0; } break; case 186: /* orderby_opt ::= */ -{yymsp[1].minor.yy207 = 0;} +{yymsp[1].minor.yy429 = 0;} break; case 187: /* orderby_opt ::= ORDER BY sortlist */ -{yymsp[-2].minor.yy207 = yymsp[0].minor.yy207;} +{yymsp[-2].minor.yy429 = yymsp[0].minor.yy429;} break; case 188: /* sortlist ::= sortlist COMMA item sortorder */ { - yylhsminor.yy207 = tVariantListAppend(yymsp[-3].minor.yy207, &yymsp[-1].minor.yy232, yymsp[0].minor.yy116); + yylhsminor.yy429 = tVariantListAppend(yymsp[-3].minor.yy429, &yymsp[-1].minor.yy218, yymsp[0].minor.yy116); } - yymsp[-3].minor.yy207 = yylhsminor.yy207; + yymsp[-3].minor.yy429 = yylhsminor.yy429; break; case 189: /* sortlist ::= item sortorder */ { - yylhsminor.yy207 = tVariantListAppend(NULL, &yymsp[-1].minor.yy232, yymsp[0].minor.yy116); + yylhsminor.yy429 = tVariantListAppend(NULL, &yymsp[-1].minor.yy218, yymsp[0].minor.yy116); } - yymsp[-1].minor.yy207 = yylhsminor.yy207; + yymsp[-1].minor.yy429 = yylhsminor.yy429; break; case 190: /* item ::= ids cpxName */ { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - tVariantCreate(&yylhsminor.yy232, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy218, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy232 = yylhsminor.yy232; + yymsp[-1].minor.yy218 = yylhsminor.yy218; break; case 191: /* sortorder ::= ASC */ { yymsp[0].minor.yy116 = TSDB_ORDER_ASC; } @@ -3103,193 +2759,193 @@ static YYACTIONTYPE yy_reduce( { yymsp[1].minor.yy116 = TSDB_ORDER_ASC; } break; case 194: /* groupby_opt ::= */ -{ yymsp[1].minor.yy207 = 0;} +{ yymsp[1].minor.yy429 = 0;} break; case 195: /* groupby_opt ::= GROUP BY grouplist */ -{ yymsp[-2].minor.yy207 = yymsp[0].minor.yy207;} +{ yymsp[-2].minor.yy429 = yymsp[0].minor.yy429;} break; case 196: /* grouplist ::= grouplist COMMA item */ { - yylhsminor.yy207 = tVariantListAppend(yymsp[-2].minor.yy207, &yymsp[0].minor.yy232, -1); + yylhsminor.yy429 = tVariantListAppend(yymsp[-2].minor.yy429, &yymsp[0].minor.yy218, -1); } - yymsp[-2].minor.yy207 = yylhsminor.yy207; + yymsp[-2].minor.yy429 = yylhsminor.yy429; break; case 197: /* grouplist ::= item */ { - yylhsminor.yy207 = tVariantListAppend(NULL, &yymsp[0].minor.yy232, -1); + yylhsminor.yy429 = tVariantListAppend(NULL, &yymsp[0].minor.yy218, -1); } - yymsp[0].minor.yy207 = yylhsminor.yy207; + yymsp[0].minor.yy429 = yylhsminor.yy429; break; case 198: /* having_opt ::= */ case 208: /* where_opt ::= */ yytestcase(yyruleno==208); case 247: /* expritem ::= */ yytestcase(yyruleno==247); -{yymsp[1].minor.yy484 = 0;} +{yymsp[1].minor.yy282 = 0;} break; case 199: /* having_opt ::= HAVING expr */ case 209: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==209); -{yymsp[-1].minor.yy484 = yymsp[0].minor.yy484;} +{yymsp[-1].minor.yy282 = yymsp[0].minor.yy282;} break; case 200: /* limit_opt ::= */ case 204: /* slimit_opt ::= */ yytestcase(yyruleno==204); -{yymsp[1].minor.yy314.limit = -1; yymsp[1].minor.yy314.offset = 0;} +{yymsp[1].minor.yy18.limit = -1; yymsp[1].minor.yy18.offset = 0;} break; case 201: /* limit_opt ::= LIMIT signed */ case 205: /* slimit_opt ::= SLIMIT signed */ yytestcase(yyruleno==205); -{yymsp[-1].minor.yy314.limit = yymsp[0].minor.yy208; yymsp[-1].minor.yy314.offset = 0;} +{yymsp[-1].minor.yy18.limit = yymsp[0].minor.yy481; yymsp[-1].minor.yy18.offset = 0;} break; case 202: /* limit_opt ::= LIMIT signed OFFSET signed */ -{ yymsp[-3].minor.yy314.limit = yymsp[-2].minor.yy208; yymsp[-3].minor.yy314.offset = yymsp[0].minor.yy208;} +{ yymsp[-3].minor.yy18.limit = yymsp[-2].minor.yy481; yymsp[-3].minor.yy18.offset = yymsp[0].minor.yy481;} break; case 203: /* limit_opt ::= LIMIT signed COMMA signed */ -{ yymsp[-3].minor.yy314.limit = yymsp[0].minor.yy208; yymsp[-3].minor.yy314.offset = yymsp[-2].minor.yy208;} +{ yymsp[-3].minor.yy18.limit = yymsp[0].minor.yy481; yymsp[-3].minor.yy18.offset = yymsp[-2].minor.yy481;} break; case 206: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ -{yymsp[-3].minor.yy314.limit = yymsp[-2].minor.yy208; yymsp[-3].minor.yy314.offset = yymsp[0].minor.yy208;} +{yymsp[-3].minor.yy18.limit = yymsp[-2].minor.yy481; yymsp[-3].minor.yy18.offset = yymsp[0].minor.yy481;} break; case 207: /* slimit_opt ::= SLIMIT signed COMMA signed */ -{yymsp[-3].minor.yy314.limit = yymsp[0].minor.yy208; yymsp[-3].minor.yy314.offset = yymsp[-2].minor.yy208;} +{yymsp[-3].minor.yy18.limit = yymsp[0].minor.yy481; yymsp[-3].minor.yy18.offset = yymsp[-2].minor.yy481;} break; case 210: /* expr ::= LP expr RP */ -{yylhsminor.yy484 = yymsp[-1].minor.yy484; yylhsminor.yy484->token.z = yymsp[-2].minor.yy0.z; yylhsminor.yy484->token.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = yymsp[-1].minor.yy282; yylhsminor.yy282->token.z = yymsp[-2].minor.yy0.z; yylhsminor.yy282->token.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 211: /* expr ::= ID */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_ID);} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_ID);} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 212: /* expr ::= ID DOT ID */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[-2].minor.yy0, TK_ID);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[-2].minor.yy0, TK_ID);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 213: /* expr ::= ID DOT STAR */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[-2].minor.yy0, TK_ALL);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[-2].minor.yy0, TK_ALL);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 214: /* expr ::= INTEGER */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_INTEGER);} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_INTEGER);} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 215: /* expr ::= MINUS INTEGER */ case 216: /* expr ::= PLUS INTEGER */ yytestcase(yyruleno==216); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[-1].minor.yy0, TK_INTEGER);} - yymsp[-1].minor.yy484 = yylhsminor.yy484; +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[-1].minor.yy0, TK_INTEGER);} + yymsp[-1].minor.yy282 = yylhsminor.yy282; break; case 217: /* expr ::= FLOAT */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_FLOAT);} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_FLOAT);} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 218: /* expr ::= MINUS FLOAT */ case 219: /* expr ::= PLUS FLOAT */ yytestcase(yyruleno==219); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[-1].minor.yy0, TK_FLOAT);} - yymsp[-1].minor.yy484 = yylhsminor.yy484; +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[-1].minor.yy0, TK_FLOAT);} + yymsp[-1].minor.yy282 = yylhsminor.yy282; break; case 220: /* expr ::= STRING */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_STRING);} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_STRING);} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 221: /* expr ::= NOW */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_NOW); } - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_NOW); } + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 222: /* expr ::= VARIABLE */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_VARIABLE);} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_VARIABLE);} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 223: /* expr ::= BOOL */ -{ yylhsminor.yy484 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_BOOL);} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_BOOL);} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 224: /* expr ::= ID LP exprlist RP */ -{ yylhsminor.yy484 = tSqlExprCreateFunction(yymsp[-1].minor.yy178, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprCreateFunction(yymsp[-1].minor.yy170, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } + yymsp[-3].minor.yy282 = yylhsminor.yy282; break; case 225: /* expr ::= ID LP STAR RP */ -{ yylhsminor.yy484 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy484 = yylhsminor.yy484; +{ yylhsminor.yy282 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } + yymsp[-3].minor.yy282 = yylhsminor.yy282; break; case 226: /* expr ::= expr IS NULL */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, NULL, TK_ISNULL);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, NULL, TK_ISNULL);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 227: /* expr ::= expr IS NOT NULL */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-3].minor.yy484, NULL, TK_NOTNULL);} - yymsp[-3].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-3].minor.yy282, NULL, TK_NOTNULL);} + yymsp[-3].minor.yy282 = yylhsminor.yy282; break; case 228: /* expr ::= expr LT expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_LT);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_LT);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 229: /* expr ::= expr GT expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_GT);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_GT);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 230: /* expr ::= expr LE expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_LE);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_LE);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 231: /* expr ::= expr GE expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_GE);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_GE);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 232: /* expr ::= expr NE expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_NE);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_NE);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 233: /* expr ::= expr EQ expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_EQ);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_EQ);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 234: /* expr ::= expr BETWEEN expr AND expr */ -{ tSQLExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy484); yylhsminor.yy484 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy484, yymsp[-2].minor.yy484, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy484, TK_LE), TK_AND);} - yymsp[-4].minor.yy484 = yylhsminor.yy484; +{ tSQLExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy282); yylhsminor.yy282 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy282, yymsp[-2].minor.yy282, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy282, TK_LE), TK_AND);} + yymsp[-4].minor.yy282 = yylhsminor.yy282; break; case 235: /* expr ::= expr AND expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_AND);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_AND);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 236: /* expr ::= expr OR expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_OR); } - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_OR); } + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 237: /* expr ::= expr PLUS expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_PLUS); } - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_PLUS); } + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 238: /* expr ::= expr MINUS expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_MINUS); } - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_MINUS); } + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 239: /* expr ::= expr STAR expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_STAR); } - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_STAR); } + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 240: /* expr ::= expr SLASH expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_DIVIDE);} - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_DIVIDE);} + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 241: /* expr ::= expr REM expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_REM); } - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_REM); } + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 242: /* expr ::= expr LIKE expr */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-2].minor.yy484, yymsp[0].minor.yy484, TK_LIKE); } - yymsp[-2].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-2].minor.yy282, yymsp[0].minor.yy282, TK_LIKE); } + yymsp[-2].minor.yy282 = yylhsminor.yy282; break; case 243: /* expr ::= expr IN LP exprlist RP */ -{yylhsminor.yy484 = tSqlExprCreate(yymsp[-4].minor.yy484, (tSQLExpr*)yymsp[-1].minor.yy178, TK_IN); } - yymsp[-4].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = tSqlExprCreate(yymsp[-4].minor.yy282, (tSQLExpr*)yymsp[-1].minor.yy170, TK_IN); } + yymsp[-4].minor.yy282 = yylhsminor.yy282; break; case 244: /* exprlist ::= exprlist COMMA expritem */ -{yylhsminor.yy178 = tSqlExprListAppend(yymsp[-2].minor.yy178,yymsp[0].minor.yy484,0, 0);} - yymsp[-2].minor.yy178 = yylhsminor.yy178; +{yylhsminor.yy170 = tSqlExprListAppend(yymsp[-2].minor.yy170,yymsp[0].minor.yy282,0, 0);} + yymsp[-2].minor.yy170 = yylhsminor.yy170; break; case 245: /* exprlist ::= expritem */ -{yylhsminor.yy178 = tSqlExprListAppend(0,yymsp[0].minor.yy484,0, 0);} - yymsp[0].minor.yy178 = yylhsminor.yy178; +{yylhsminor.yy170 = tSqlExprListAppend(0,yymsp[0].minor.yy282,0, 0);} + yymsp[0].minor.yy170 = yylhsminor.yy170; break; case 246: /* expritem ::= expr */ -{yylhsminor.yy484 = yymsp[0].minor.yy484;} - yymsp[0].minor.yy484 = yylhsminor.yy484; +{yylhsminor.yy282 = yymsp[0].minor.yy282;} + yymsp[0].minor.yy282 = yylhsminor.yy282; break; case 248: /* cmd ::= RESET QUERY CACHE */ { setDCLSQLElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} @@ -3297,7 +2953,7 @@ static YYACTIONTYPE yy_reduce( case 249: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy207, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); + SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy429, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; @@ -3315,7 +2971,7 @@ static YYACTIONTYPE yy_reduce( case 251: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy207, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy429, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; @@ -3350,7 +3006,7 @@ static YYACTIONTYPE yy_reduce( toTSDBType(yymsp[-2].minor.yy0.type); SArray* A = tVariantListAppendToken(NULL, &yymsp[-2].minor.yy0, -1); - A = tVariantListAppend(A, &yymsp[0].minor.yy232, -1); + A = tVariantListAppend(A, &yymsp[0].minor.yy218, -1); SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-6].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); @@ -3359,7 +3015,7 @@ static YYACTIONTYPE yy_reduce( case 255: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy207, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy429, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; @@ -3377,7 +3033,7 @@ static YYACTIONTYPE yy_reduce( case 257: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy207, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy429, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; @@ -3419,9 +3075,9 @@ static YYACTIONTYPE yy_reduce( break; /********** End reduce actions ************************************************/ }; - assert( yyrulenostateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact, "... then shift"); - return yyact; } /* @@ -3446,8 +3101,7 @@ static YYACTIONTYPE yy_reduce( static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ - ParseARG_FETCH - ParseCTX_FETCH + ParseARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); @@ -3458,8 +3112,7 @@ static void yy_parse_failed( ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ - ParseCTX_STORE + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* YYNOERRORRECOVERY */ @@ -3471,8 +3124,7 @@ static void yy_syntax_error( int yymajor, /* The major type of the error token */ ParseTOKENTYPE yyminor /* The minor type of the error token */ ){ - ParseARG_FETCH - ParseCTX_FETCH + ParseARG_FETCH; #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ @@ -3498,8 +3150,7 @@ static void yy_syntax_error( assert(len <= outputBufLen); /************ End %syntax_error code ******************************************/ - ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ - ParseCTX_STORE + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* @@ -3508,8 +3159,7 @@ static void yy_syntax_error( static void yy_accept( yyParser *yypParser /* The parser */ ){ - ParseARG_FETCH - ParseCTX_FETCH + ParseARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); @@ -3524,8 +3174,7 @@ static void yy_accept( /*********** Begin %parse_accept code *****************************************/ /*********** End %parse_accept code *******************************************/ - ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ - ParseCTX_STORE + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* The main parser program. @@ -3554,47 +3203,45 @@ void Parse( ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; - YYACTIONTYPE yyact; /* The parser action. */ + unsigned int yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif - yyParser *yypParser = (yyParser*)yyp; /* The parser */ - ParseCTX_FETCH - ParseARG_STORE + yyParser *yypParser; /* The parser */ + yypParser = (yyParser*)yyp; assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif + ParseARG_STORE; - yyact = yypParser->yytos->stateno; #ifndef NDEBUG if( yyTraceFILE ){ - if( yyact < YY_MIN_REDUCE ){ + int stateno = yypParser->yytos->stateno; + if( stateno < YY_MIN_REDUCE ){ fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact); + yyTracePrompt,yyTokenName[yymajor],stateno); }else{ fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); + yyTracePrompt,yyTokenName[yymajor],stateno-YY_MIN_REDUCE); } } #endif do{ - assert( yyact==yypParser->yytos->stateno ); - yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); + yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); if( yyact >= YY_MIN_REDUCE ){ - yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, - yyminor ParseCTX_PARAM); + yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor); }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); + yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif - break; + yymajor = YYNOCODE; }else if( yyact==YY_ACCEPT_ACTION ){ yypParser->yytos--; yy_accept(yypParser); @@ -3645,9 +3292,10 @@ void Parse( yymajor = YYNOCODE; }else{ while( yypParser->yytos >= yypParser->yystack + && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, - YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE + YYERRORSYMBOL)) >= YY_MIN_REDUCE ){ yy_pop_parser_stack(yypParser); } @@ -3664,8 +3312,6 @@ void Parse( } yypParser->yyerrcnt = 3; yyerrorhit = 1; - if( yymajor==YYNOCODE ) break; - yyact = yypParser->yytos->stateno; #elif defined(YYNOERRORRECOVERY) /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax @@ -3676,7 +3322,8 @@ void Parse( */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - break; + yymajor = YYNOCODE; + #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** @@ -3698,10 +3345,10 @@ void Parse( yypParser->yyerrcnt = -1; #endif } - break; + yymajor = YYNOCODE; #endif } - }while( yypParser->yytos>yypParser->yystack ); + }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ yyStackEntry *i; @@ -3716,17 +3363,3 @@ void Parse( #endif return; } - -/* -** Return the fallback token corresponding to canonical token iToken, or -** 0 if iToken has no fallback. -*/ -int ParseFallback(int iToken){ -#ifdef YYFALLBACK - assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); - return yyFallback[iToken]; -#else - (void)iToken; - return 0; -#endif -} diff --git a/src/query/tests/resultBufferTest.cpp b/src/query/tests/resultBufferTest.cpp index 7b946d858913b14dfdbb71eb1b8a8c469e6d930c..19e011774241dffa156a0ecb003041aba8253ba5 100644 --- a/src/query/tests/resultBufferTest.cpp +++ b/src/query/tests/resultBufferTest.cpp @@ -10,7 +10,7 @@ namespace { // simple test void simpleTest() { SDiskbasedResultBuf* pResultBuf = NULL; - int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 64, 1024, 4096, NULL); + int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 1024, 4096, NULL); int32_t pageId = 0; int32_t groupId = 0; @@ -52,7 +52,7 @@ void simpleTest() { void writeDownTest() { SDiskbasedResultBuf* pResultBuf = NULL; - int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 64, 1024, 4*1024, NULL); + int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 1024, 4*1024, NULL); int32_t pageId = 0; int32_t writePageId = 0; @@ -99,7 +99,7 @@ void writeDownTest() { void recyclePageTest() { SDiskbasedResultBuf* pResultBuf = NULL; - int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 64, 1024, 4*1024, NULL); + int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 1024, 4*1024, NULL); int32_t pageId = 0; int32_t writePageId = 0; diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index e0648c33a050fcdb5a6cd83517283092b1061d5e..0bf533d027db284a12ae155dc494fd8f9f35a5f1 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -34,11 +34,9 @@ .tid = (_checkInfo)->tableId.tid, \ .uid = (_checkInfo)->tableId.uid}) - enum { TSDB_QUERY_TYPE_ALL = 1, TSDB_QUERY_TYPE_LAST = 2, - TSDB_QUERY_TYPE_EXTERNAL = 3, }; typedef struct SQueryFilePos { @@ -68,7 +66,7 @@ typedef struct STableCheckInfo { STableId tableId; TSKEY lastKey; STable* pTableObj; - SBlockInfo* pCompInfo; + SBlockInfo* pCompInfo; int32_t compSize; int32_t numOfBlocks:29; // number of qualified data blocks not the original blocks int8_t chosen:2; // indicate which iterator should move forward @@ -78,8 +76,8 @@ typedef struct STableCheckInfo { } STableCheckInfo; typedef struct STableBlockInfo { - SBlock* compBlock; - STableCheckInfo* pTableCheckInfo; + SBlock *compBlock; + STableCheckInfo *pTableCheckInfo; } STableBlockInfo; typedef struct SBlockOrderSupporter { @@ -111,6 +109,8 @@ typedef struct STsdbQueryHandle { bool checkFiles; // check file stage bool cachelastrow; // check if last row cached bool loadExternalRow; // load time window external data rows + bool currentLoadExternalRows; // current load external rows + int32_t loadType; // block load type void* qinfo; // query info handle, for debug purpose int32_t type; // query type: retrieve all data blocks, 2. retrieve only last row, 3. retrieve direct prev|next rows SDFileSet* pFileGroup; @@ -147,6 +147,8 @@ static int32_t tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, static int32_t tsdbCheckInfoCompar(const void* key1, const void* key2); static int32_t doGetExternalRow(STsdbQueryHandle* pQueryHandle, int16_t type, SMemRef* pMemRef); static void* doFreeColumnInfoData(SArray* pColumnInfoData); +static void* destroyTableCheckInfo(SArray* pTableCheckInfo); +static bool tsdbGetExternalRow(TsdbQueryHandleT pHandle); static void tsdbInitDataBlockLoadInfo(SDataBlockLoadInfo* pBlockLoadInfo) { pBlockLoadInfo->slot = -1; @@ -294,40 +296,48 @@ static SArray* createCheckInfoFromTableGroup(STsdbQueryHandle* pQueryHandle, STa taosArraySort(pTableCheckInfo, tsdbCheckInfoCompar); size_t gsize = taosArrayGetSize(pTableCheckInfo); - + for (int32_t i = 0; i < gsize; ++i) { STableCheckInfo* pInfo = (STableCheckInfo*) taosArrayGet(pTableCheckInfo, i); - taosArrayPush(pTable, &pInfo->pTableObj); } *psTable = pTable; - return pTableCheckInfo; } -static SArray* createCheckInfoFromCheckInfo(SArray* pTableCheckInfo, TSKEY skey, SArray** psTable) { - size_t si = taosArrayGetSize(pTableCheckInfo); - SArray* pNew = taosArrayInit(si, sizeof(STableCheckInfo)); - if (pNew == NULL) { - return NULL; +static void resetCheckInfo(STsdbQueryHandle* pQueryHandle) { + size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + assert(numOfTables >= 1); + + // todo apply the lastkey of table check to avoid to load header file + for (int32_t i = 0; i < numOfTables; ++i) { + STableCheckInfo* pCheckInfo = (STableCheckInfo*) taosArrayGet(pQueryHandle->pTableCheckInfo, i); + pCheckInfo->lastKey = pQueryHandle->window.skey; + pCheckInfo->iter = tSkipListDestroyIter(pCheckInfo->iter); + pCheckInfo->iiter = tSkipListDestroyIter(pCheckInfo->iiter); + pCheckInfo->initBuf = false; + + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + assert(pCheckInfo->lastKey >= pQueryHandle->window.skey); + } else { + assert(pCheckInfo->lastKey <= pQueryHandle->window.skey); + } } +} - SArray* pTable = taosArrayInit(si, sizeof(STable*)); +// only one table, not need to sort again +static SArray* createCheckInfoFromCheckInfo(STableCheckInfo* pCheckInfo, TSKEY skey, SArray** psTable) { + SArray* pNew = taosArrayInit(1, sizeof(STableCheckInfo)); + SArray* pTable = taosArrayInit(1, sizeof(STable*)); - for (int32_t j = 0; j < si; ++j) { - STableCheckInfo* pCheckInfo = (STableCheckInfo*) taosArrayGet(pTableCheckInfo, j); - STableCheckInfo info = { .lastKey = skey, .pTableObj = pCheckInfo->pTableObj}; + STableCheckInfo info = { .lastKey = skey, .pTableObj = pCheckInfo->pTableObj}; - info.tableId = pCheckInfo->tableId; - taosArrayPush(pNew, &info); - taosArrayPush(pTable, &pCheckInfo->pTableObj); - } + info.tableId = pCheckInfo->tableId; + taosArrayPush(pNew, &info); + taosArrayPush(pTable, &pCheckInfo->pTableObj); *psTable = pTable; - - // it is ordered already, no need to sort again. - taosArraySort(pNew, tsdbCheckInfoCompar); return pNew; } @@ -351,14 +361,15 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC pQueryHandle->locateStart = false; pQueryHandle->pMemRef = pMemRef; pQueryHandle->loadExternalRow = pCond->loadExternalRows; + pQueryHandle->currentLoadExternalRows = pCond->loadExternalRows; + + pQueryHandle->loadType = pCond->type; if (tsdbInitReadH(&pQueryHandle->rhelper, (STsdbRepo*)tsdb) != 0) { goto out_of_memory; } - //tsdbMayTakeMemSnapshot(pQueryHandle); assert(pCond != NULL && pCond->numOfCols > 0 && pMemRef != NULL); - if (ASCENDING_TRAVERSE(pCond->order)) { assert(pQueryHandle->window.skey <= pQueryHandle->window.ekey); } else { @@ -388,7 +399,9 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC pQueryHandle->statis[i].colId = colInfo.info.colId; } - pQueryHandle->defaultLoadColumn = getDefaultLoadColumns(pQueryHandle, true); + if (pCond->numOfCols > 0) { + pQueryHandle->defaultLoadColumn = getDefaultLoadColumns(pQueryHandle, true); + } STsdbMeta* pMeta = tsdbGetMeta(tsdb); assert(pMeta != NULL); @@ -433,6 +446,74 @@ TsdbQueryHandleT* tsdbQueryTables(STsdbRepo* tsdb, STsdbQueryCond* pCond, STable return (TsdbQueryHandleT) pQueryHandle; } +void tsdbResetQueryHandle(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond) { + STsdbQueryHandle* pQueryHandle = queryHandle; + + pQueryHandle->order = pCond->order; + pQueryHandle->window = pCond->twindow; + pQueryHandle->type = TSDB_QUERY_TYPE_ALL; + pQueryHandle->cur.fid = -1; + pQueryHandle->cur.win = TSWINDOW_INITIALIZER; + pQueryHandle->checkFiles = true; + pQueryHandle->activeIndex = 0; // current active table index + pQueryHandle->locateStart = false; + pQueryHandle->loadExternalRow = pCond->loadExternalRows; + + if (ASCENDING_TRAVERSE(pCond->order)) { + assert(pQueryHandle->window.skey <= pQueryHandle->window.ekey); + } else { + assert(pQueryHandle->window.skey >= pQueryHandle->window.ekey); + } + + // allocate buffer in order to load data blocks from file + memset(pQueryHandle->statis, 0, sizeof(SDataStatis)); + + tsdbInitDataBlockLoadInfo(&pQueryHandle->dataBlockLoadInfo); + tsdbInitCompBlockLoadInfo(&pQueryHandle->compBlockLoadInfo); + + resetCheckInfo(pQueryHandle); +} + +void tsdbResetQueryHandleForNewTable(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond, STableGroupInfo* groupList) { + STsdbQueryHandle* pQueryHandle = queryHandle; + + pQueryHandle->order = pCond->order; + pQueryHandle->window = pCond->twindow; + pQueryHandle->type = TSDB_QUERY_TYPE_ALL; + pQueryHandle->cur.fid = -1; + pQueryHandle->cur.win = TSWINDOW_INITIALIZER; + pQueryHandle->checkFiles = true; + pQueryHandle->activeIndex = 0; // current active table index + pQueryHandle->locateStart = false; + pQueryHandle->loadExternalRow = pCond->loadExternalRows; + + if (ASCENDING_TRAVERSE(pCond->order)) { + assert(pQueryHandle->window.skey <= pQueryHandle->window.ekey); + } else { + assert(pQueryHandle->window.skey >= pQueryHandle->window.ekey); + } + + // allocate buffer in order to load data blocks from file + memset(pQueryHandle->statis, 0, sizeof(SDataStatis)); + + tsdbInitDataBlockLoadInfo(&pQueryHandle->dataBlockLoadInfo); + tsdbInitCompBlockLoadInfo(&pQueryHandle->compBlockLoadInfo); + + SArray* pTable = NULL; + STsdbMeta* pMeta = tsdbGetMeta(pQueryHandle->pTsdb); + + pQueryHandle->pTableCheckInfo = destroyTableCheckInfo(pQueryHandle->pTableCheckInfo); + + pQueryHandle->pTableCheckInfo = createCheckInfoFromTableGroup(pQueryHandle, groupList, pMeta, &pTable); + if (pQueryHandle->pTableCheckInfo == NULL) { + tsdbCleanupQueryHandle(pQueryHandle); + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + } + + pQueryHandle->prev = doFreeColumnInfoData(pQueryHandle->prev); + pQueryHandle->next = doFreeColumnInfoData(pQueryHandle->next); +} + TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, void* qinfo, SMemRef* pMemRef) { pCond->twindow = updateLastrowForEachGroup(groupList); @@ -469,12 +550,45 @@ SArray* tsdbGetQueriedTableList(TsdbQueryHandleT *pHandle) { return res; } +// leave only one table for each group +static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGroupList) { + assert(pGroupList); + size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList); + + STableGroupInfo* pNew = calloc(1, sizeof(STableGroupInfo)); + pNew->pGroupList = taosArrayInit(numOfGroup, sizeof(SArray)); + + for(int32_t i = 0; i < numOfGroup; ++i) { + SArray* oneGroup = taosArrayGetP(pGroupList->pGroupList, i); + size_t numOfTables = taosArrayGetSize(oneGroup); + + SArray* px = taosArrayInit(4, sizeof(STableKeyInfo)); + for (int32_t j = 0; j < numOfTables; ++j) { + STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(oneGroup, j); + if (window->skey <= pInfo->lastKey && ((STable*)pInfo->pTable)->lastKey != TSKEY_INITIAL_VAL) { + taosArrayPush(px, pInfo); + pNew->numOfTables += 1; + break; + } + } + + // there are no data in this group + if (taosArrayGetSize(px) == 0) { + taosArrayDestroy(px); + } else { + taosArrayPush(pNew->pGroupList, &px); + } + } + + return pNew; +} + TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond* pCond, STableGroupInfo *groupList, void* qinfo, SMemRef* pRef) { - STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, groupList, qinfo, pRef); + STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList); + + STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, pNew, qinfo, pRef); pQueryHandle->loadExternalRow = true; - if (pQueryHandle != NULL) { - changeQueryHandleForInterpQuery(pQueryHandle); - } + pQueryHandle->currentLoadExternalRows = true; return pQueryHandle; } @@ -769,77 +883,94 @@ static int32_t binarySearchForBlock(SBlock* pBlock, int32_t numOfBlocks, TSKEY s return midSlot; } -static int32_t getFileCompInfo(STsdbQueryHandle* pQueryHandle, int32_t* numOfBlocks) { - // load all the comp offset value for all tables in this file - int32_t code = TSDB_CODE_SUCCESS; +static int32_t loadBlockInfo(STsdbQueryHandle * pQueryHandle, int32_t index, int32_t* numOfBlocks) { + int32_t code = 0; - *numOfBlocks = 0; - size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, index); + pCheckInfo->numOfBlocks = 0; - for (int32_t i = 0; i < numOfTables; ++i) { - STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); - pCheckInfo->numOfBlocks = 0; + if (tsdbSetReadTable(&pQueryHandle->rhelper, pCheckInfo->pTableObj) != TSDB_CODE_SUCCESS) { + code = terrno; + return code; + } - if (tsdbSetReadTable(&pQueryHandle->rhelper, pCheckInfo->pTableObj) != TSDB_CODE_SUCCESS) { - code = terrno; - break; - } + SBlockIdx* compIndex = pQueryHandle->rhelper.pBlkIdx; + + // no data block in this file, try next file + if (compIndex == NULL || compIndex->uid != pCheckInfo->tableId.uid) { + return 0; // no data blocks in the file belongs to pCheckInfo->pTable + } - SBlockIdx* compIndex = pQueryHandle->rhelper.pBlkIdx; + if (pCheckInfo->compSize < (int32_t)compIndex->len) { + assert(compIndex->len > 0); - // no data block in this file, try next file - if (compIndex == NULL || compIndex->uid != pCheckInfo->tableId.uid) { - continue; // no data blocks in the file belongs to pCheckInfo->pTable + char* t = realloc(pCheckInfo->pCompInfo, compIndex->len); + if (t == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + code = TSDB_CODE_TDB_OUT_OF_MEMORY; + return code; } - if (pCheckInfo->compSize < (int32_t)compIndex->len) { - assert(compIndex->len > 0); + pCheckInfo->pCompInfo = (SBlockInfo*)t; + pCheckInfo->compSize = compIndex->len; + } - char* t = realloc(pCheckInfo->pCompInfo, compIndex->len); - if (t == NULL) { - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - code = TSDB_CODE_TDB_OUT_OF_MEMORY; - break; - } + tsdbLoadBlockInfo(&(pQueryHandle->rhelper), (void*)(pCheckInfo->pCompInfo)); + SBlockInfo* pCompInfo = pCheckInfo->pCompInfo; - pCheckInfo->pCompInfo = (SBlockInfo*) t; - pCheckInfo->compSize = compIndex->len; - } + TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL; - tsdbLoadBlockInfo(&(pQueryHandle->rhelper), (void *)(pCheckInfo->pCompInfo)); - SBlockInfo* pCompInfo = pCheckInfo->pCompInfo; + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + assert(pCheckInfo->lastKey <= pQueryHandle->window.ekey && pQueryHandle->window.skey <= pQueryHandle->window.ekey); + } else { + assert(pCheckInfo->lastKey >= pQueryHandle->window.ekey && pQueryHandle->window.skey >= pQueryHandle->window.ekey); + } - TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL; + s = MIN(pCheckInfo->lastKey, pQueryHandle->window.ekey); + e = MAX(pCheckInfo->lastKey, pQueryHandle->window.ekey); - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - assert(pCheckInfo->lastKey <= pQueryHandle->window.ekey && pQueryHandle->window.skey <= pQueryHandle->window.ekey); - } else { - assert(pCheckInfo->lastKey >= pQueryHandle->window.ekey && pQueryHandle->window.skey >= pQueryHandle->window.ekey); - } + // discard the unqualified data block based on the query time window + int32_t start = binarySearchForBlock(pCompInfo->blocks, compIndex->numOfBlocks, s, TSDB_ORDER_ASC); + int32_t end = start; - s = MIN(pCheckInfo->lastKey, pQueryHandle->window.ekey); - e = MAX(pCheckInfo->lastKey, pQueryHandle->window.ekey); + if (s > pCompInfo->blocks[start].keyLast) { + return 0; + } - // discard the unqualified data block based on the query time window - int32_t start = binarySearchForBlock(pCompInfo->blocks, compIndex->numOfBlocks, s, TSDB_ORDER_ASC); - int32_t end = start; + // todo speedup the procedure of located end block + while (end < (int32_t)compIndex->numOfBlocks && (pCompInfo->blocks[end].keyFirst <= e)) { + end += 1; + } - if (s > pCompInfo->blocks[start].keyLast) { - continue; - } + pCheckInfo->numOfBlocks = (end - start); - // todo speedup the procedure of located end block - while (end < (int32_t)compIndex->numOfBlocks && (pCompInfo->blocks[end].keyFirst <= e)) { - end += 1; - } + if (start > 0) { + memmove(pCompInfo->blocks, &pCompInfo->blocks[start], pCheckInfo->numOfBlocks * sizeof(SBlock)); + } - pCheckInfo->numOfBlocks = (end - start); + (*numOfBlocks) += pCheckInfo->numOfBlocks; + return 0; +} - if (start > 0) { - memmove(pCompInfo->blocks, &pCompInfo->blocks[start], pCheckInfo->numOfBlocks * sizeof(SBlock)); - } +static int32_t getFileCompInfo(STsdbQueryHandle* pQueryHandle, int32_t* numOfBlocks) { + // load all the comp offset value for all tables in this file + int32_t code = TSDB_CODE_SUCCESS; + *numOfBlocks = 0; + + size_t numOfTables = 0; + if (pQueryHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) { + code = loadBlockInfo(pQueryHandle, pQueryHandle->activeIndex, numOfBlocks); + } else if (pQueryHandle->loadType == BLOCK_LOAD_OFFSET_SEQ_ORDER) { + numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - (*numOfBlocks) += pCheckInfo->numOfBlocks; + for (int32_t i = 0; i < numOfTables; ++i) { + code = loadBlockInfo(pQueryHandle, i, numOfBlocks); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + } else { + assert(0); } return code; @@ -1268,7 +1399,7 @@ static void copyOneRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, case TSDB_DATA_TYPE_DOUBLE: SET_DOUBLE_PTR(pData, value); break; - case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_TIMESTAMP: *(TSKEY *)pData = tdGetKey(*(TKEY *)value); break; default: @@ -1730,6 +1861,7 @@ static int32_t createDataBlocksInfo(STsdbQueryHandle* pQueryHandle, int32_t numO memset(pQueryHandle->pDataBlockInfo, 0, size); *numOfAllocBlocks = numOfBlocks; + // access data blocks according to the offset of each block in asc/desc order. int32_t numOfTables = (int32_t)taosArrayGetSize(pQueryHandle->pTableCheckInfo); SBlockOrderSupporter sup = {0}; @@ -1959,6 +2091,91 @@ static void moveToNextDataBlockInCurrentFile(STsdbQueryHandle* pQueryHandle) { cur->blockCompleted = false; } +int32_t tsdbGetFileBlocksDistInfo(TsdbQueryHandleT* queryHandle, STableBlockDist* pTableBlockInfo) { + STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) queryHandle; + + pTableBlockInfo->totalSize = 0; + STsdbFS* pFileHandle = REPO_FS(pQueryHandle->pTsdb); + + // find the start data block in file + pQueryHandle->locateStart = true; + STsdbCfg* pCfg = &pQueryHandle->pTsdb->config; + int32_t fid = getFileIdFromKey(pQueryHandle->window.skey, pCfg->daysPerFile, pCfg->precision); + + tsdbRLockFS(pFileHandle); + tsdbFSIterInit(&pQueryHandle->fileIter, pFileHandle, pQueryHandle->order); + tsdbFSIterSeek(&pQueryHandle->fileIter, fid); + tsdbUnLockFS(pFileHandle); + + pTableBlockInfo->numOfFiles += 1; + + int32_t code = TSDB_CODE_SUCCESS; + int32_t numOfBlocks = 0; + int32_t numOfTables = (int32_t)taosArrayGetSize(pQueryHandle->pTableCheckInfo); + STimeWindow win = TSWINDOW_INITIALIZER; + + while (true) { + numOfBlocks = 0; + tsdbRLockFS(REPO_FS(pQueryHandle->pTsdb)); + + if ((pQueryHandle->pFileGroup = tsdbFSIterNext(&pQueryHandle->fileIter)) == NULL) { + tsdbUnLockFS(REPO_FS(pQueryHandle->pTsdb)); + break; + } + + tsdbGetFidKeyRange(pCfg->daysPerFile, pCfg->precision, pQueryHandle->pFileGroup->fid, &win.skey, &win.ekey); + + // current file are not overlapped with query time window, ignore remain files + if ((ASCENDING_TRAVERSE(pQueryHandle->order) && win.skey > pQueryHandle->window.ekey) || + (!ASCENDING_TRAVERSE(pQueryHandle->order) && win.ekey < pQueryHandle->window.ekey)) { + tsdbUnLockFS(REPO_FS(pQueryHandle->pTsdb)); + tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %p", pQueryHandle, + pQueryHandle->window.skey, pQueryHandle->window.ekey, pQueryHandle->qinfo); + pQueryHandle->pFileGroup = NULL; + break; + } + + pTableBlockInfo->numOfFiles += 1; + if (tsdbSetAndOpenReadFSet(&pQueryHandle->rhelper, pQueryHandle->pFileGroup) < 0) { + tsdbUnLockFS(REPO_FS(pQueryHandle->pTsdb)); + code = terrno; + break; + } + + tsdbUnLockFS(REPO_FS(pQueryHandle->pTsdb)); + + if (tsdbLoadBlockIdx(&pQueryHandle->rhelper) < 0) { + code = terrno; + break; + } + + if ((code = getFileCompInfo(pQueryHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) { + break; + } + + tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %p", pQueryHandle, numOfBlocks, numOfTables, + pQueryHandle->pFileGroup->fid, pQueryHandle->qinfo); + + if (numOfBlocks == 0) { + continue; + } + + for (int32_t i = 0; i < numOfTables; ++i) { + STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); + + SBlock* pBlock = pCheckInfo->pCompInfo->blocks; + for (int32_t j = 0; j < pCheckInfo->numOfBlocks; ++j) { + pTableBlockInfo->totalSize += pBlock[j].len; + + int32_t numOfRows = pBlock[j].numOfRows; + taosArrayPush(pTableBlockInfo->dataBlockInfos, &numOfRows); + } + } + } + + return code; +} + static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists) { STsdbFS* pFileHandle = REPO_FS(pQueryHandle->pTsdb); SQueryFilePos* cur = &pQueryHandle->cur; @@ -2017,19 +2234,14 @@ static bool doHasDataInBuffer(STsdbQueryHandle* pQueryHandle) { pQueryHandle->activeIndex += 1; } - if (pQueryHandle->loadExternalRow && pQueryHandle->window.skey == pQueryHandle->window.ekey) { - SMemRef* pMemRef = pQueryHandle->pMemRef; - doGetExternalRow(pQueryHandle, TSDB_PREV_ROW, pMemRef); - doGetExternalRow(pQueryHandle, TSDB_NEXT_ROW, pMemRef); - } - // no data in memtable or imemtable, decrease the memory reference. - tsdbMayUnTakeMemSnapshot(pQueryHandle); + // TODO !! +// tsdbMayUnTakeMemSnapshot(pQueryHandle); return false; } //todo not unref yet, since it is not support multi-group interpolation query -static void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle) { +static UNUSED_FUNC void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle) { // filter the queried time stamp in the first place STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle; @@ -2152,149 +2364,164 @@ static void destroyHelper(void* param) { free(param); } -// handle data in cache situation -bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { - STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle; - - int64_t stime = taosGetTimestampUs(); - int64_t elapsedTime = stime; - - size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - assert(numOfTables > 0); - - if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST && pQueryHandle->cachelastrow) { - // the last row is cached in buffer, return it directly. - // here note that the pQueryHandle->window must be the TS_INITIALIZER - int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); - SQueryFilePos* cur = &pQueryHandle->cur; - - SDataRow pRow = NULL; - TSKEY key = TSKEY_INITIAL_VAL; - int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; - - if (++pQueryHandle->activeIndex < numOfTables) { - STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); - int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key); - if (ret != TSDB_CODE_SUCCESS) { - return false; - } - - copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, numOfCols, pCheckInfo->pTableObj, NULL); - tfree(pRow); - - // update the last key value - pCheckInfo->lastKey = key + step; - - cur->rows = 1; // only one row - cur->lastKey = key + step; - cur->mixBlock = true; - cur->win.skey = key; - cur->win.ekey = key; - - return true; - } - - return false; - } - +static bool loadBlockOfActiveTable(STsdbQueryHandle* pQueryHandle) { if (pQueryHandle->checkFiles) { // check if the query range overlaps with the file data block bool exists = true; int32_t code = getDataBlocksInFiles(pQueryHandle, &exists); if (code != TSDB_CODE_SUCCESS) { - pQueryHandle->activeIndex = 0; pQueryHandle->checkFiles = false; - return false; } if (exists) { - pQueryHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime); + if (pQueryHandle->currentLoadExternalRows && pQueryHandle->window.skey == pQueryHandle->window.ekey) { + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, 0); + assert(*(int64_t*)pColInfo->pData == pQueryHandle->window.skey); + } + + pQueryHandle->currentLoadExternalRows = false; // clear the flag, since the exact matched row is found. return exists; } - pQueryHandle->activeIndex = 0; pQueryHandle->checkFiles = false; } - // TODO: opt by consider the scan order - bool ret = doHasDataInBuffer(pQueryHandle); - terrno = TSDB_CODE_SUCCESS; + if (hasMoreDataInCache(pQueryHandle)) { + pQueryHandle->currentLoadExternalRows = false; + return true; + } - elapsedTime = taosGetTimestampUs() - stime; - pQueryHandle->cost.checkForNextTime += elapsedTime; - return ret; + // current result is empty + if (pQueryHandle->currentLoadExternalRows && pQueryHandle->window.skey == pQueryHandle->window.ekey && pQueryHandle->cur.rows == 0) { + SMemRef* pMemRef = pQueryHandle->pMemRef; + + doGetExternalRow(pQueryHandle, TSDB_PREV_ROW, pMemRef); + doGetExternalRow(pQueryHandle, TSDB_NEXT_ROW, pMemRef); + + bool result = tsdbGetExternalRow(pQueryHandle); + + pQueryHandle->prev = doFreeColumnInfoData(pQueryHandle->prev); + pQueryHandle->next = doFreeColumnInfoData(pQueryHandle->next); + pQueryHandle->currentLoadExternalRows = false; + + return result; + } + + return false; } -bool tsdbNextDataBlockWithoutMerge(TsdbQueryHandleT* pHandle) { - STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle; +static bool loadCachedLastRow(STsdbQueryHandle* pQueryHandle) { + // the last row is cached in buffer, return it directly. + // here note that the pQueryHandle->window must be the TS_INITIALIZER + int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); + size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + assert(numOfTables > 0 && numOfCols > 0); - int64_t stime = taosGetTimestampUs(); - int64_t elapsedTime = stime; + SQueryFilePos* cur = &pQueryHandle->cur; - size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - assert(numOfTables > 0); + SDataRow pRow = NULL; + TSKEY key = TSKEY_INITIAL_VAL; + int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; - if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST && pQueryHandle->cachelastrow) { - // the last row is cached in buffer, return it directly. - // here note that the pQueryHandle->window must be the TS_INITIALIZER - int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); - SQueryFilePos* cur = &pQueryHandle->cur; - - SDataRow pRow = NULL; - TSKEY key = TSKEY_INITIAL_VAL; - int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; - - if (++pQueryHandle->activeIndex < numOfTables) { - STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); - int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key); - if (ret != TSDB_CODE_SUCCESS) { - return false; - } + if (++pQueryHandle->activeIndex < numOfTables) { + STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); + int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key); + if (ret != TSDB_CODE_SUCCESS) { + return false; + } - copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, numOfCols, pCheckInfo->pTableObj, NULL); - tfree(pRow); + copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, numOfCols, pCheckInfo->pTableObj, NULL); + tfree(pRow); - // update the last key value - pCheckInfo->lastKey = key + step; + // update the last key value + pCheckInfo->lastKey = key + step; - cur->rows = 1; // only one row - cur->lastKey = key + step; - cur->mixBlock = true; - cur->win.skey = key; - cur->win.ekey = key; + cur->rows = 1; // only one row + cur->lastKey = key + step; + cur->mixBlock = true; + cur->win.skey = key; + cur->win.ekey = key; + + return true; + } + + return false; +} + +static bool loadDataBlockFromTableSeq(STsdbQueryHandle* pQueryHandle) { + size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + assert(numOfTables > 0); + + int64_t stime = taosGetTimestampUs(); + while(pQueryHandle->activeIndex < numOfTables) { + if (loadBlockOfActiveTable(pQueryHandle)) { return true; } - return false; + STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); + pCheckInfo->numOfBlocks = 0; + + pQueryHandle->activeIndex += 1; + pQueryHandle->locateStart = false; + pQueryHandle->checkFiles = true; + pQueryHandle->cur.rows = 0; + pQueryHandle->currentLoadExternalRows = pQueryHandle->loadExternalRow; + + terrno = TSDB_CODE_SUCCESS; + + int64_t elapsedTime = taosGetTimestampUs() - stime; + pQueryHandle->cost.checkForNextTime += elapsedTime; } - if (pQueryHandle->checkFiles) { - // check if the query range overlaps with the file data block - bool exists = true; + return false; +} + +// handle data in cache situation +bool tsdbNextDataBlock(TsdbQueryHandleT pHandle) { + STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle; + + int64_t stime = taosGetTimestampUs(); + int64_t elapsedTime = stime; + + if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST && pQueryHandle->cachelastrow) { + return loadCachedLastRow(pQueryHandle); + } + + if (pQueryHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) { + return loadDataBlockFromTableSeq(pQueryHandle); + } else { // loadType == RR and Offset Order + if (pQueryHandle->checkFiles) { + // check if the query range overlaps with the file data block + bool exists = true; + + int32_t code = getDataBlocksInFiles(pQueryHandle, &exists); + if (code != TSDB_CODE_SUCCESS) { + pQueryHandle->activeIndex = 0; + pQueryHandle->checkFiles = false; + + return false; + } + + if (exists) { + pQueryHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime); + return exists; + } - int32_t code = getDataBlocksInFiles(pQueryHandle, &exists); - if (code != TSDB_CODE_SUCCESS) { pQueryHandle->activeIndex = 0; pQueryHandle->checkFiles = false; - - return false; } - if (exists) { - pQueryHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime); - return exists; - } + // TODO: opt by consider the scan order + bool ret = doHasDataInBuffer(pQueryHandle); + terrno = TSDB_CODE_SUCCESS; - pQueryHandle->activeIndex = 0; - pQueryHandle->checkFiles = false; + elapsedTime = taosGetTimestampUs() - stime; + pQueryHandle->cost.checkForNextTime += elapsedTime; + return ret; } - - elapsedTime = taosGetTimestampUs() - stime; - pQueryHandle->cost.checkForNextTime += elapsedTime; - return false; } static int32_t doGetExternalRow(STsdbQueryHandle* pQueryHandle, int16_t type, SMemRef* pMemRef) { @@ -2342,7 +2569,7 @@ static int32_t doGetExternalRow(STsdbQueryHandle* pQueryHandle, int16_t type, SM } // load the previous row - STsdbQueryCond cond = {.numOfCols = numOfCols, .loadExternalRows = false,}; + STsdbQueryCond cond = {.numOfCols = numOfCols, .loadExternalRows = false, .type = BLOCK_LOAD_OFFSET_SEQ_ORDER}; if (type == TSDB_PREV_ROW) { cond.order = TSDB_ORDER_DESC; cond.twindow = (STimeWindow){pQueryHandle->window.skey, INT64_MIN}; @@ -2363,20 +2590,20 @@ static int32_t doGetExternalRow(STsdbQueryHandle* pQueryHandle, int16_t type, SM } pSecQueryHandle = tsdbQueryTablesImpl(pQueryHandle->pTsdb, &cond, pQueryHandle->qinfo, pMemRef); - tfree(cond.colList); + // current table, only one table + STableCheckInfo* pCurrent = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); + SArray* psTable = NULL; - - pSecQueryHandle->pTableCheckInfo = createCheckInfoFromCheckInfo(pQueryHandle->pTableCheckInfo, pSecQueryHandle->window.skey, &psTable); + pSecQueryHandle->pTableCheckInfo = createCheckInfoFromCheckInfo(pCurrent, pSecQueryHandle->window.skey, &psTable); if (pSecQueryHandle->pTableCheckInfo == NULL) { terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; goto out_of_memory; } - - tsdbMayTakeMemSnapshot(pSecQueryHandle, psTable); + tsdbMayTakeMemSnapshot(pSecQueryHandle, psTable); if (!tsdbNextDataBlock((void*)pSecQueryHandle)) { // no result in current query, free the corresponding result rows structure if (type == TSDB_PREV_ROW) { @@ -2406,10 +2633,35 @@ out_of_memory: return terrno; } -SArray* tsdbGetExternalRow(TsdbQueryHandleT *pHandle, SMemRef* pMemRef, int16_t type) { +bool tsdbGetExternalRow(TsdbQueryHandleT pHandle) { STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle; - assert(type == TSDB_PREV_ROW || type == TSDB_NEXT_ROW); - return (type == TSDB_PREV_ROW)? pQueryHandle->prev:pQueryHandle->next; + SQueryFilePos* cur = &pQueryHandle->cur; + + cur->fid = INT32_MIN; + cur->mixBlock = true; + if (pQueryHandle->prev == NULL || pQueryHandle->next == NULL) { + cur->rows = 0; + return false; + } + + int32_t numOfCols = (int32_t) QH_GET_NUM_OF_COLS(pQueryHandle); + for (int32_t i = 0; i < numOfCols; ++i) { + SColumnInfoData* pColInfoData = taosArrayGet(pQueryHandle->pColumns, i); + SColumnInfoData* first = taosArrayGet(pQueryHandle->prev, i); + + memcpy(pColInfoData->pData, first->pData, pColInfoData->info.bytes); + + SColumnInfoData* sec = taosArrayGet(pQueryHandle->next, i); + memcpy(((char*)pColInfoData->pData) + pColInfoData->info.bytes, sec->pData, pColInfoData->info.bytes); + + if (i == 0 && pColInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) { + cur->win.skey = *(TSKEY*)pColInfoData->pData; + cur->win.ekey = *(TSKEY*)(((char*)pColInfoData->pData) + TSDB_KEYSIZE); + } + } + + cur->rows = 2; + return true; } /* @@ -2949,10 +3201,10 @@ int32_t tsdbQuerySTableByTagCond(STsdbRepo* tsdb, uint64_t uid, TSKEY skey, cons goto _error; } - pGroupInfo->numOfTables = taosArrayGetSize(res); + pGroupInfo->numOfTables = (uint32_t) taosArrayGetSize(res); pGroupInfo->pGroupList = createTableGroup(res, pTagSchema, pColIndex, numOfCols, skey); - tsdbDebug("%p no table name/tag condition, all tables belong to one group, numOfTables:%" PRIzu "", tsdb, pGroupInfo->numOfTables); + tsdbDebug("%p no table name/tag condition, all tables belong to one group, numOfTables:%u", tsdb, pGroupInfo->numOfTables); taosArrayDestroy(res); if (tsdbUnlockRepoMeta(tsdb) < 0) goto _error; @@ -2994,10 +3246,10 @@ int32_t tsdbQuerySTableByTagCond(STsdbRepo* tsdb, uint64_t uid, TSKEY skey, cons } END_TRY doQueryTableList(pTable, res, expr); - pGroupInfo->numOfTables = taosArrayGetSize(res); + pGroupInfo->numOfTables = (uint32_t)taosArrayGetSize(res); pGroupInfo->pGroupList = createTableGroup(res, pTagSchema, pColIndex, numOfCols, skey); - tsdbDebug("%p stable tid:%d, uid:%"PRIu64" query, numOfTables:%" PRIzu ", belong to %" PRIzu " groups", tsdb, pTable->tableId.tid, + tsdbDebug("%p stable tid:%d, uid:%"PRIu64" query, numOfTables:%u, belong to %" PRIzu " groups", tsdb, pTable->tableId.tid, pTable->tableId.uid, pGroupInfo->numOfTables, taosArrayGetSize(pGroupInfo->pGroupList)); taosArrayDestroy(res); @@ -3074,7 +3326,7 @@ int32_t tsdbGetTableGroupFromIdList(STsdbRepo* tsdb, SArray* pTableIdList, STabl return terrno; } - pGroupInfo->numOfTables = taosArrayGetSize(group); + pGroupInfo->numOfTables = (uint32_t) taosArrayGetSize(group); if (pGroupInfo->numOfTables > 0) { taosArrayPush(pGroupInfo->pGroupList, &group); } else { @@ -3099,23 +3351,26 @@ static void* doFreeColumnInfoData(SArray* pColumnInfoData) { return NULL; } +static void* destroyTableCheckInfo(SArray* pTableCheckInfo) { + size_t size = taosArrayGetSize(pTableCheckInfo); + for (int32_t i = 0; i < size; ++i) { + STableCheckInfo* p = taosArrayGet(pTableCheckInfo, i); + destroyTableMemIterator(p); + + tfree(p->pCompInfo); + } + + taosArrayDestroy(pTableCheckInfo); + return NULL; +} + void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle) { STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*)queryHandle; if (pQueryHandle == NULL) { return; } - - if (pQueryHandle->pTableCheckInfo != NULL) { - size_t size = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - for (int32_t i = 0; i < size; ++i) { - STableCheckInfo* pTableCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); - destroyTableMemIterator(pTableCheckInfo); - - tfree(pTableCheckInfo->pCompInfo); - } - taosArrayDestroy(pQueryHandle->pTableCheckInfo); - } + pQueryHandle->pTableCheckInfo = destroyTableCheckInfo(pQueryHandle->pTableCheckInfo); pQueryHandle->pColumns = doFreeColumnInfoData(pQueryHandle->pColumns); taosArrayDestroy(pQueryHandle->defaultLoadColumn); diff --git a/src/util/inc/tarray.h b/src/util/inc/tarray.h index 63e62a54c2f679920100b7137cb49377da90789f..f2e268c2d4dfe210dfbfd9b94ee74a4f87848361 100644 --- a/src/util/inc/tarray.h +++ b/src/util/inc/tarray.h @@ -25,7 +25,8 @@ extern "C" { #define TARRAY_MIN_SIZE 8 #define TARRAY_GET_ELEM(array, index) ((void*)((char*)((array)->pData) + (index) * (array)->elemSize)) -#define TARRAY_ELEM_IDX(array, ele) (POINTER_DISTANCE(ele, (array)->pData) / (array)->elemSize) +#define TARRAY_ELEM_IDX(array, ele) (POINTER_DISTANCE(ele, (array)->pData) / (array)->elemSize) +#define TARRAY_GET_START(array) ((array)->pData) typedef struct SArray { size_t size; diff --git a/src/util/inc/tbuffer.h b/src/util/inc/tbuffer.h index e2bdb815d7ac8ecd09b62a3a62897b78ebf3c4b7..b19984b4be047108fd9848a2a7eddbac2c0b78a4 100644 --- a/src/util/inc/tbuffer.h +++ b/src/util/inc/tbuffer.h @@ -73,14 +73,14 @@ int main( int argc, char** argv ) { } */ -typedef struct { +typedef struct SBufferReader { bool endian; const char* data; size_t pos; size_t size; } SBufferReader; -typedef struct { +typedef struct SBufferWriter { bool endian; char* data; size_t pos; diff --git a/tests/script/general/cache/new_metrics.sim b/tests/script/general/cache/new_metrics.sim index 00cbe843f955c618f8dfca56d9633eb911038d5e..eb9b042483251856c2ac7b3f973ab31176a8ff56 100644 --- a/tests/script/general/cache/new_metrics.sim +++ b/tests/script/general/cache/new_metrics.sim @@ -94,8 +94,9 @@ while $i < 10 $i = $i + 1 endw -print ==> sleep 8 seconds to renew cache -sleep 8000 +print ==> sleep 1 seconds to renew cache +sql reset query cache +sleep 1000 print =============== step5 diff --git a/tests/script/general/cache/restart_metrics.sim b/tests/script/general/cache/restart_metrics.sim index 4f2dae5fd95eba03de931234f6a71204948cb78a..a1b2365b2aef739d7bdf97ba82b757648285fe97 100644 --- a/tests/script/general/cache/restart_metrics.sim +++ b/tests/script/general/cache/restart_metrics.sim @@ -55,7 +55,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/exec.sh -n dnode1 -s start print =============== step3 -print ==> sleep 8 seconds to renew cache +print ==> sleep 1 seconds to renew cache sql reset query cache sleep 1000 diff --git a/tests/script/general/cache/restart_table.sim b/tests/script/general/cache/restart_table.sim index 9b0d8f9c5b483b79da41fb4e86c17902d328a89d..1f7d982a2848a5df443f32a8c2b5c1edb97874d2 100644 --- a/tests/script/general/cache/restart_table.sim +++ b/tests/script/general/cache/restart_table.sim @@ -39,10 +39,9 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/exec.sh -n dnode1 -s start print =============== step3 -print ==> sleep 8 seconds to renew cache -sleep 2000 +print ==> sleep 1 seconds to renew cache sql reset query cache -sleep 18000 +sleep 1000 print =============== step4 sql create database $db diff --git a/tests/script/general/parser/col_arithmetic_operation.sim b/tests/script/general/parser/col_arithmetic_operation.sim index 7611bd582fc76d0e2c3fe2fe51bc2dcd74e7fbbe..8bb692e3bbe8af3ec9ed179ad29d40b4712d257b 100644 --- a/tests/script/general/parser/col_arithmetic_operation.sim +++ b/tests/script/general/parser/col_arithmetic_operation.sim @@ -93,6 +93,7 @@ $halfTbNum = $tbNum / 2 $nchar = 'nchar . $c $nchar = $nchar . ' + $ts = $ts + 1 sql insert into $tb5 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $tb6 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $tb7 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $tb8 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $tb9 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $x = $x + 1 endw diff --git a/tests/script/general/parser/col_arithmetic_query.sim b/tests/script/general/parser/col_arithmetic_query.sim index 3f1a430e2bb5bab1112708a9925d74d27f030cc5..2c56c6445fa8134ab28837940a11ff6f4127b7c7 100644 --- a/tests/script/general/parser/col_arithmetic_query.sim +++ b/tests/script/general/parser/col_arithmetic_query.sim @@ -426,7 +426,7 @@ if $data02 != 9.000000020 then endi # all possible function in the arithmetic expression, add more -sql select min(c1) * max(c2) /4, sum(c1) * apercentile(c2, 20), apercentile(c4, 33) + 52/9, spread(c5)/min(c2), count(1)/sum(c1), avg(c2)*count(c2) from $stb where ts >= '2018-09-17 09:00:00.000' and ts <= '2018-11-25 19:30:00.000'; +sql select min(c1) * max(c2) /4, sum(c1) * apercentile(c2, 20), apercentile(c4, 33) + 52/9, spread(c5)/min(c2), count(1)/sum(c1), avg(c2)*count(c2) from $stb where ts >= '2018-09-17 09:00:00.000' and ts <= '2018-11-25 19:30:01.000'; if $rows != 1 then return -1 endi @@ -462,7 +462,7 @@ if $rows != 0 then endi # no result return [d.3] -sql select sum(c2) - avg(c2) from $stb where ts > '2018-11-25 19:30:00.000' +sql select sum(c2) - avg(c2) from $stb where ts > '2018-11-25 19:30:01.000' if $rows != 0 then return -1 endi @@ -520,35 +520,35 @@ if $data91 != 9 then endi # in group by column -sql select apercentile(c6, 50)-first(c6)+last(c5)*12, last(c5)*12 from ca_stb0 group by c2; -if $rows != 10 then - return -1 -endi - -if $data00 != 0.000000000 then - return -1 -endi - -if $data01 != 0.000000000 then - return -1 -endi - -if $data10 != 12.000000000 then - return -1 -endi - -if $data11 != 12.000000000 then - return -1 -endi - -if $data20 != 24.000000000 then - return -1 -endi - -if $data21 != 24.000000000 then - return -1 -endi - +#sql select apercentile(c6, 50)-first(c6)+last(c5)*12, last(c5)*12 from ca_stb0 group by c2; +#if $rows != 10 then +# return -1 +#endi +# +#if $data00 != 0.000000000 then +# return -1 +#endi +# +#if $data01 != 0.000000000 then +# return -1 +#endi +# +#if $data10 != 12.000000000 then +# return -1 +#endi +# +#if $data11 != 12.000000000 then +# return -1 +#endi +# +#if $data20 != 24.000000000 then +# return -1 +#endi +# +#if $data21 != 24.000000000 then +# return -1 +#endi +# sql_error select first(c6) - last(c6) *12 / count(*) from $stb group by c3; sql select first(c6) - last(c6) *12 / count(*) from $stb group by c5; diff --git a/tests/script/general/parser/fill.sim b/tests/script/general/parser/fill.sim index 7bf00145d619f2455a35686b9fd7424efbcc3f2a..d109dd50f7c0ba0684295dbf093ba1b280e04fce 100644 --- a/tests/script/general/parser/fill.sim +++ b/tests/script/general/parser/fill.sim @@ -313,6 +313,7 @@ if $rows != 9 then return -1 endi if $data01 != 0 then + print expect 0, actual:$data01 return -1 endi if $data11 != 6 then @@ -979,10 +980,6 @@ if $data00 != @20-01-01 01:01:00.000@ then return -1 endi -if $data00 != @20-01-01 01:01:00.000@ then - return -1 -endi -if $data1 if $data01 != 2.000000000 then return -1 endi diff --git a/tests/script/general/parser/function.sim b/tests/script/general/parser/function.sim index 8eb6aa55f2d06f4d90e14cd4035d2c460b6b1b00..9165b7e98e0510c3fead45acbc1baeceb0b653a3 100644 --- a/tests/script/general/parser/function.sim +++ b/tests/script/general/parser/function.sim @@ -775,8 +775,24 @@ if $rows != 1 then return -1 endi - if $data00 != 0.000000000 then return -1 endi +sql select count(tbname) from st1 +if $rows != 1 then + return -1 +endi + +if $data00 != 1 then + return -1 +endi + +sql select count(id) from st1 +if $rows != 1 then + return -1 +endi + +if $data00 != 1 then + return -1 +endi diff --git a/tests/script/general/parser/interp_test.sim b/tests/script/general/parser/interp_test.sim index 28601808306334286d2a9691626a2b1c1d211b30..81a77995fb828db00b65d085e0839e3b652385e0 100644 --- a/tests/script/general/parser/interp_test.sim +++ b/tests/script/general/parser/interp_test.sim @@ -579,7 +579,7 @@ $tb = $tbPrefix . 0 ## interp(*) from stb + group by + fill(none) $t = $ts0 + 1000 - sql select interp(*) from $stb where ts = $t fill(NULL) group by tbname +sql select interp(*) from $stb where ts = $t fill(NULL) group by tbname if $rows != $tbNum then return -1 endi diff --git a/tests/script/general/parser/join.sim b/tests/script/general/parser/join.sim index 392228e12122bcbcd0d336ec9dbf32a0cf9ef4c5..73f83f1c9e2af21e49099ffd73a6b1e9d040b2eb 100644 --- a/tests/script/general/parser/join.sim +++ b/tests/script/general/parser/join.sim @@ -347,6 +347,7 @@ $val = $rowNum + $rowNum print $val print $rows if $rows != $val then + print expect $val , actual:$rows return -1 endi diff --git a/tests/script/general/parser/limit1_stb.sim b/tests/script/general/parser/limit1_stb.sim index a0e3a45d2fc28002e2e64b195191b72659849a53..513e2fac026c0d1d617ba4126d22c01f82527ca0 100644 --- a/tests/script/general/parser/limit1_stb.sim +++ b/tests/script/general/parser/limit1_stb.sim @@ -538,6 +538,7 @@ $offset = $offset + 1 sql select max(c1), min(c2), avg(c3), count(c4), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and t1 > 1 and t1 < 8 interval(5m) limit $offset offset $offset $val = $rowNum - $offset if $rows != $val then + print expect $val, actual:$rows return -1 endi if $data00 != @18-10-22 02:30:00.000@ then diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index 255389a2df12e470890ca74e9b3872a28bc119c3..c2ce5df12e9e4d60824950f21ac8afb9d64b5235 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -107,3 +107,6 @@ sleep 100 run general/parser/function.sim sleep 100 run general/parser/stableOp.sim +sleep 100 +run general/parser/slimit_alter_tags.sim + diff --git a/tests/script/general/parser/topbot.sim b/tests/script/general/parser/topbot.sim index 3e73e4967be505d80ebf47809e63c89bc2846a04..80a122238ec70136daa444b78764f5881563451d 100644 --- a/tests/script/general/parser/topbot.sim +++ b/tests/script/general/parser/topbot.sim @@ -73,6 +73,60 @@ if $row != 100 then return -1 endi +sql select bottom(c3, 5) from tb_tb1 interval(1y); +if $rows != 5 then + return -1 +endi + +if $data01 != 0.00000 then + print expect 0.00000, actual:$data01 + return -1 +endi + +if $data11 != 0.00000 then + return -1 +endi + +if $data21 != 0.00000 then + return -1 +endi + +if $data31 != 0.00000 then + return -1 +endi + +sql select top(c4, 5) from tb_tb1 interval(1y); +if $rows != 5 then + return -1 +endi + +if $data01 != 9.000000000 then + print expect 9.000000000, acutal:$data01 + return -1 +endi + +if $data11 != 9.000000000 then + return -1 +endi + +if $data21 != 9.000000000 then + return -1 +endi + +if $data31 != 9.000000000 then + return -1 +endi + +sql select top(c3, 5) from tb_tb1 interval(40h) +if $rows != 25 then + return -1 +endi + +if $data01 != 9.00000 then + print expect 9.00000, actual:$data01 + return -1 +endi + sql select last(*) from tb_tb9 if $row != 1 then return -1 diff --git a/tests/script/general/stream/restart_stream.sim b/tests/script/general/stream/restart_stream.sim index 5da69075361da7c2fad3ed9fde7384493fac9519..c8be10103d16a856fb0c083546cfaf8b939a1b98 100644 --- a/tests/script/general/stream/restart_stream.sim +++ b/tests/script/general/stream/restart_stream.sim @@ -100,8 +100,9 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/exec.sh -n dnode1 -s start print =============== step5 -print ==> sleep 8 seconds to renew cache -sleep 8000 +print ==> renew cache +sql reset query cache +sleep 1000 print =============== step6 diff --git a/tests/script/jenkins/basic_1.txt b/tests/script/jenkins/basic_1.txt index 17245767344e50389d10bc997be33abb78c289ef..ae72e76b2f6c444e84fdaee3818200983796ace3 100644 --- a/tests/script/jenkins/basic_1.txt +++ b/tests/script/jenkins/basic_1.txt @@ -22,8 +22,6 @@ ./test.sh -f general/http/grafana_bug.sim ./test.sh -f general/http/grafana.sim - - ./test.sh -f general/insert/basic.sim ./test.sh -f general/insert/insert_drop.sim ./test.sh -f general/insert/query_block1_memory.sim