提交 25aa2933 编写于 作者: wmmhello's avatar wmmhello

modify unique function like top

上级 dfad8aca
...@@ -593,7 +593,7 @@ static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput ...@@ -593,7 +593,7 @@ static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput
} }
} }
static void doMergeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, int32_t numOfExpr, int32_t rowIndex, char** pDataPtr) { static void doMergeResultImpl(SOperatorInfo* pInfo, SQLFunctionCtx *pCtx, int32_t numOfExpr, int32_t rowIndex, char** pDataPtr) {
for (int32_t j = 0; j < numOfExpr; ++j) { for (int32_t j = 0; j < numOfExpr; ++j) {
pCtx[j].pInput = pDataPtr[j] + pCtx[j].inputBytes * rowIndex; pCtx[j].pInput = pDataPtr[j] + pCtx[j].inputBytes * rowIndex;
} }
...@@ -605,12 +605,20 @@ static void doMergeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, i ...@@ -605,12 +605,20 @@ static void doMergeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, i
} }
if (functionId < 0) { if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); SUdfInfo* pUdfInfo = taosArrayGet(((SMultiwayMergeInfo*)(pInfo->info))->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE); doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
} else { } else {
assert(!TSDB_FUNC_IS_SCALAR(functionId)); assert(!TSDB_FUNC_IS_SCALAR(functionId));
aAggs[functionId].mergeFunc(&pCtx[j]); aAggs[functionId].mergeFunc(&pCtx[j]);
} }
SQueryAttr* pQueryAttr = pInfo->pRuntimeEnv->pQueryAttr;
if (functionId == TSDB_FUNC_UNIQUE &&
(GET_RES_INFO(&(pCtx[j]))->numOfRes > MAX_UNIQUE_RESULT_ROWS || GET_RES_INFO(&(pCtx[j]))->numOfRes == -1)){
tscError("Unique result num is too large. num: %d, limit: %d",
GET_RES_INFO(&(pCtx[j]))->numOfRes, MAX_UNIQUE_RESULT_ROWS);
longjmp(pInfo->pRuntimeEnv->env, TSDB_CODE_QRY_UNIQUE_RESULT_TOO_LARGE);
}
} }
} }
...@@ -644,7 +652,7 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD ...@@ -644,7 +652,7 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
for(int32_t i = 0; i < pBlock->info.rows; ++i) { for(int32_t i = 0; i < pBlock->info.rows; ++i) {
if (pInfo->hasPrev) { if (pInfo->hasPrev) {
if (needToMerge(pBlock, pInfo->orderColumnList, i, pInfo->prevRow)) { if (needToMerge(pBlock, pInfo->orderColumnList, i, pInfo->prevRow)) {
doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr); doMergeResultImpl(pOperator, pCtx, numOfExpr, i, addrPtr);
} else { } else {
doFinalizeResultImpl(pInfo, pCtx, numOfExpr); doFinalizeResultImpl(pInfo, pCtx, numOfExpr);
...@@ -671,10 +679,10 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD ...@@ -671,10 +679,10 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
} }
} }
doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr); doMergeResultImpl(pOperator, pCtx, numOfExpr, i, addrPtr);
} }
} else { } else {
doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr); doMergeResultImpl(pOperator, pCtx, numOfExpr, i, addrPtr);
} }
savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, i, &pInfo->hasPrev); savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, i, &pInfo->hasPrev);
......
...@@ -3106,601 +3106,587 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col ...@@ -3106,601 +3106,587 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
size_t cnt = taosArrayGetSize(pItem->pNode->Expr.paramList); size_t cnt = taosArrayGetSize(pItem->pNode->Expr.paramList);
if (cnt != 2 && cnt != 3) valid = false; if (cnt != 2 && cnt != 3) valid = false;
} else if (functionId == TSDB_FUNC_UNIQUE) { } else if (functionId == TSDB_FUNC_UNIQUE) {
if (taosArrayGetSize(pItem->pNode->Expr.paramList) != 1) if (taosArrayGetSize(pItem->pNode->Expr.paramList) != 1) valid = false;
valid = false; }else {
else { if (taosArrayGetSize(pItem->pNode->Expr.paramList) != 2) valid = false;
if (taosArrayGetSize(pItem->pNode->Expr.paramList) != 2) valid = false; }
} if (!valid) {
if (!valid) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); }
}
tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0); tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0);
if (pParamElem->pNode->tokenId != TK_ID) { if (pParamElem->pNode->tokenId != TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
SColumnIndex index = COLUMN_INDEX_INITIALIZER; SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) !=
TSDB_CODE_SUCCESS) { TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
} }
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
} }
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
// functions can not be applied to tags // functions can not be applied to tags
if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
} }
// 2. valid the column type // 2. valid the column type
if (functionId != TSDB_FUNC_SAMPLE && !IS_NUMERIC_TYPE(pSchema->type)) { if (functionId != TSDB_FUNC_SAMPLE && !IS_NUMERIC_TYPE(pSchema->type)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
tVariant* pVariant = NULL;
if (functionId != TSDB_FUNC_UNIQUE) {
// 3. valid the parameters
if (pParamElem[1].pNode->tokenId == TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
tVariant* pVariant = NULL; pVariant = &pParamElem[1].pNode->value;
if (functionId != TSDB_FUNC_UNIQUE) { }
// 3. valid the parameters
if (pParamElem[1].pNode->tokenId == TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
pVariant = &pParamElem[1].pNode->value; int16_t resultType = pSchema->type;
} int32_t resultSize = pSchema->bytes;
int32_t interResult = 0;
int16_t resultType = pSchema->type; char val[8] = {0};
int32_t resultSize = pSchema->bytes;
int32_t interResult = 0;
char val[8] = {0}; SExprInfo* pExpr = NULL;
if (functionId == TSDB_FUNC_PERCT || functionId == TSDB_FUNC_APERCT) {
// param1 double
if (pVariant->nType != TSDB_DATA_TYPE_DOUBLE && pVariant->nType != TSDB_DATA_TYPE_BIGINT) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
tVariantDump(pVariant, val, TSDB_DATA_TYPE_DOUBLE, true);
SExprInfo* pExpr = NULL; double dp = GET_DOUBLE_VAL(val);
if (functionId == TSDB_FUNC_PERCT || functionId == TSDB_FUNC_APERCT) { if (dp < 0 || dp > TOP_BOTTOM_QUERY_LIMIT) {
// param1 double return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
if (pVariant->nType != TSDB_DATA_TYPE_DOUBLE && pVariant->nType != TSDB_DATA_TYPE_BIGINT) { }
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
tVariantDump(pVariant, val, TSDB_DATA_TYPE_DOUBLE, true);
double dp = GET_DOUBLE_VAL(val); getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize, &interResult, 0,
if (dp < 0 || dp > TOP_BOTTOM_QUERY_LIMIT) { false, pUdfInfo);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize, &interResult, 0, /*
false, pUdfInfo); * sql function transformation
* for dp = 0, it is actually min,
/* * for dp = 100, it is max,
* sql function transformation */
* for dp = 0, it is actually min, tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
* for dp = 100, it is max, colIndex += 1; // the first column is ts
*/
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid); pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
colIndex += 1; // the first column is ts interResult, false);
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double));
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
interResult, false); // param2 int32
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double)); if (taosArrayGetSize(pItem->pNode->Expr.paramList) == 3) {
if (pParamElem[2].pNode != NULL) {
// param2 int32 pVariant = &pParamElem[2].pNode->value;
if (taosArrayGetSize(pItem->pNode->Expr.paramList) == 3) { // check type must string
if (pParamElem[2].pNode != NULL) { if (pVariant->nType != TSDB_DATA_TYPE_BINARY || pVariant->pz == NULL) {
pVariant = &pParamElem[2].pNode->value; return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg13);
// check type must string
if (pVariant->nType != TSDB_DATA_TYPE_BINARY || pVariant->pz == NULL) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg13);
}
char* pzAlgo = pVariant->pz;
int32_t algo = 0;
if (strcasecmp(pzAlgo, "t-digest") == 0) {
algo = 1;
} else if (strcasecmp(pzAlgo, "default") == 0) {
algo = 0;
} else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg14);
}
// append algo int32_t
tscExprAddParams(&pExpr->base, (char*)&algo, TSDB_DATA_TYPE_INT, sizeof(int32_t));
} }
char* pzAlgo = pVariant->pz;
int32_t algo = 0;
if (strcasecmp(pzAlgo, "t-digest") == 0) {
algo = 1;
} else if (strcasecmp(pzAlgo, "default") == 0) {
algo = 0;
} else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg14);
}
// append algo int32_t
tscExprAddParams(&pExpr->base, (char*)&algo, TSDB_DATA_TYPE_INT, sizeof(int32_t));
} }
} else if (functionId == TSDB_FUNC_MAVG || functionId == TSDB_FUNC_SAMPLE) { }
if (pVariant->nType != TSDB_DATA_TYPE_BIGINT) { } else if (functionId == TSDB_FUNC_MAVG || functionId == TSDB_FUNC_SAMPLE) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); if (pVariant->nType != TSDB_DATA_TYPE_BIGINT) {
} return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
char* endptr = NULL; char* endptr = NULL;
strtoll(pParamElem[1].pNode->exprToken.z, &endptr, 10); strtoll(pParamElem[1].pNode->exprToken.z, &endptr, 10);
if ((endptr - pParamElem[1].pNode->exprToken.z != pParamElem[1].pNode->exprToken.n) || errno == ERANGE) { if ((endptr - pParamElem[1].pNode->exprToken.z != pParamElem[1].pNode->exprToken.n) || errno == ERANGE) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg18); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg18);
} }
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true); tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true);
int64_t numRowsSelected = GET_INT64_VAL(val); int64_t numRowsSelected = GET_INT64_VAL(val);
if (numRowsSelected <= 0 || numRowsSelected > 1000) { if (numRowsSelected <= 0 || numRowsSelected > 1000) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg15); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg15);
} }
// todo REFACTOR // todo REFACTOR
// set the first column ts for top/bottom query // set the first column ts for top/bottom query
int32_t tsFuncId = (functionId == TSDB_FUNC_MAVG) ? TSDB_FUNC_TS_DUMMY : TSDB_FUNC_TS; int32_t tsFuncId = (functionId == TSDB_FUNC_MAVG) ? TSDB_FUNC_TS_DUMMY : TSDB_FUNC_TS;
SColumnIndex index1 = {index.tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX}; SColumnIndex index1 = {index.tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
pExpr = tscExprAppend(pQueryInfo, tsFuncId, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, 0, 0, false); pExpr = tscExprAppend(pQueryInfo, tsFuncId, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, 0, 0, false);
tstrncpy(pExpr->base.aliasName, aAggs[tsFuncId].name, sizeof(pExpr->base.aliasName)); tstrncpy(pExpr->base.aliasName, aAggs[tsFuncId].name, sizeof(pExpr->base.aliasName));
const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
SColumnList ids = createColumnList(1, index.tableIndex, TS_COLUMN_INDEX);
insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[tsFuncId].name,
pExpr);
colIndex += 1; // the first column is ts
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, (int32_t)numRowsSelected, &resultType,
&resultSize, &interResult, 0, false, pUdfInfo);
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
interResult, false);
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t));
} else if (functionId == TSDB_FUNC_UNIQUE) {
SColumnIndex index1 = {index.tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
pExpr = tscExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, 0, 0, false);
tstrncpy(pExpr->base.aliasName, aAggs[TSDB_FUNC_TS].name, sizeof(pExpr->base.aliasName));
const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
SColumnList ids = createColumnList(1, index.tableIndex, TS_COLUMN_INDEX);
insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP,
aAggs[TSDB_FUNC_TS].name, pExpr);
colIndex += 1; // the first column is ts
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
resultSize, false);
} else {
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true);
int64_t numRowsSelected = GET_INT32_VAL(val); const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
if (numRowsSelected <= 0 || numRowsSelected > 100) { // todo use macro SColumnList ids = createColumnList(1, index.tableIndex, TS_COLUMN_INDEX);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg12); insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[tsFuncId].name,
} pExpr);
// todo REFACTOR colIndex += 1; // the first column is ts
// set the first column ts for top/bottom query
SColumnIndex index1 = {index.tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
pExpr = tscExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, 0, 0, false);
tstrncpy(pExpr->base.aliasName, aAggs[TSDB_FUNC_TS].name, sizeof(pExpr->base.aliasName));
const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX; getResultDataInfo(pSchema->type, pSchema->bytes, functionId, (int32_t)numRowsSelected, &resultType,
SColumnList ids = createColumnList(1, index.tableIndex, TS_COLUMN_INDEX); &resultSize, &interResult, 0, false, pUdfInfo);
insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
aAggs[TSDB_FUNC_TS].name, pExpr); interResult, false);
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t));
} else {
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true);
colIndex += 1; // the first column is ts int64_t numRowsSelected = GET_INT32_VAL(val);
if (numRowsSelected <= 0 || numRowsSelected > 100) { // todo use macro
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg12);
}
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd), if(functionId == TSDB_FUNC_UNIQUE){
resultSize, false); GET_INT32_VAL(val) = MAX_UNIQUE_RESULT_ROWS;
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t));
} }
// todo REFACTOR
// set the first column ts for top/bottom query
SColumnIndex index1 = {index.tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
pExpr = tscExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, 0, 0, false);
tstrncpy(pExpr->base.aliasName, aAggs[TSDB_FUNC_TS].name, sizeof(pExpr->base.aliasName));
memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName)); const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1); SColumnList ids = createColumnList(1, index.tableIndex, TS_COLUMN_INDEX);
insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP,
aAggs[TSDB_FUNC_TS].name, pExpr);
// todo refactor: tscColumnListInsert part colIndex += 1; // the first column is ts
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
if (finalResult) { pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
insertResultField(pQueryInfo, colIndex, &ids, resultSize, (int8_t)resultType, pExpr->base.aliasName, pExpr); resultSize, false);
} else { tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t));
assert(ids.num == 1); }
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
}
return TSDB_CODE_SUCCESS; memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName));
getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1);
// todo refactor: tscColumnListInsert part
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
if (finalResult) {
insertResultField(pQueryInfo, colIndex, &ids, resultSize, (int8_t)resultType, pExpr->base.aliasName, pExpr);
} else {
assert(ids.num == 1);
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
} }
case TSDB_FUNC_TID_TAG: { return TSDB_CODE_SUCCESS;
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); }
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
// no parameters or more than one parameter for function case TSDB_FUNC_TID_TAG: {
if (pItem->pNode->Expr.paramList == NULL || taosArrayGetSize(pItem->pNode->Expr.paramList) != 1) { pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
} return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
tSqlExprItem* pParamItem = taosArrayGet(pItem->pNode->Expr.paramList, 0); // no parameters or more than one parameter for function
tSqlExpr* pParam = pParamItem->pNode; if (pItem->pNode->Expr.paramList == NULL || taosArrayGetSize(pItem->pNode->Expr.paramList) != 1) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
SColumnIndex index = COLUMN_INDEX_INITIALIZER; tSqlExprItem* pParamItem = taosArrayGet(pItem->pNode->Expr.paramList, 0);
if (getColumnIndexByName(&pParam->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != tSqlExpr* pParam = pParamItem->pNode;
TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); SColumnIndex index = COLUMN_INDEX_INITIALIZER;
SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); if (getColumnIndexByName(&pParam->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) !=
TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
// functions can not be applied to normal columns pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
int32_t numOfCols = tscGetNumOfColumns(pTableMetaInfo->pTableMeta); SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
if (index.columnIndex < numOfCols && index.columnIndex != TSDB_TBNAME_COLUMN_INDEX) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
if (index.columnIndex > 0) { // functions can not be applied to normal columns
index.columnIndex -= numOfCols; int32_t numOfCols = tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
} if (index.columnIndex < numOfCols && index.columnIndex != TSDB_TBNAME_COLUMN_INDEX) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
// 2. valid the column type if (index.columnIndex > 0) {
int16_t colType = 0; index.columnIndex -= numOfCols;
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { }
colType = TSDB_DATA_TYPE_BINARY;
} else {
colType = pSchema[index.columnIndex].type;
}
if (colType == TSDB_DATA_TYPE_BOOL) { // 2. valid the column type
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); int16_t colType = 0;
} if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
colType = TSDB_DATA_TYPE_BINARY;
} else {
colType = pSchema[index.columnIndex].type;
}
tscColumnListInsert(pTableMetaInfo->tagColList, index.columnIndex, pTableMetaInfo->pTableMeta->id.uid, if (colType == TSDB_DATA_TYPE_BOOL) {
&pSchema[index.columnIndex]); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); }
SSchema s = {0}; tscColumnListInsert(pTableMetaInfo->tagColList, index.columnIndex, pTableMetaInfo->pTableMeta->id.uid,
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { &pSchema[index.columnIndex]);
s = *tGetTbnameColumnSchema(); SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
} else {
s = pTagSchema[index.columnIndex]; SSchema s = {0};
} if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
s = *tGetTbnameColumnSchema();
} else {
s = pTagSchema[index.columnIndex];
}
int32_t bytes = 0; int32_t bytes = 0;
int16_t type = 0; int16_t type = 0;
int32_t inter = 0; int32_t inter = 0;
int32_t ret = getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0, NULL); int32_t ret = getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0, NULL);
assert(ret == TSDB_CODE_SUCCESS); assert(ret == TSDB_CODE_SUCCESS);
s.type = (uint8_t)type; s.type = (uint8_t)type;
s.bytes = bytes; s.bytes = bytes;
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY); TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY);
tscAddFuncInSelectClause(pQueryInfo, 0, TSDB_FUNC_TID_TAG, &index, &s, TSDB_COL_TAG, getNewResColId(pCmd)); tscAddFuncInSelectClause(pQueryInfo, 0, TSDB_FUNC_TID_TAG, &index, &s, TSDB_COL_TAG, getNewResColId(pCmd));
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
}
case TSDB_FUNC_BLKINFO: {
// no parameters or more than one parameter for function
if (pItem->pNode->Expr.paramList != NULL && taosArrayGetSize(pItem->pNode->Expr.paramList) != 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
case TSDB_FUNC_BLKINFO: { SColumnIndex index = {
// no parameters or more than one parameter for function .tableIndex = 0,
if (pItem->pNode->Expr.paramList != NULL && taosArrayGetSize(pItem->pNode->Expr.paramList) != 0) { .columnIndex = 0,
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); };
} pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SColumnIndex index = { int32_t inter = 0;
.tableIndex = 0, int16_t resType = 0;
.columnIndex = 0, int32_t bytes = 0;
};
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
int32_t inter = 0; getResultDataInfo(TSDB_DATA_TYPE_INT, 4, TSDB_FUNC_BLKINFO, 0, &resType, &bytes, &inter, 0, 0, NULL);
int16_t resType = 0;
int32_t bytes = 0;
getResultDataInfo(TSDB_DATA_TYPE_INT, 4, TSDB_FUNC_BLKINFO, 0, &resType, &bytes, &inter, 0, 0, NULL); SSchema s = {.name = "block_dist", .type = TSDB_DATA_TYPE_BINARY, .bytes = bytes};
SSchema s = {.name = "block_dist", .type = TSDB_DATA_TYPE_BINARY, .bytes = bytes}; SExprInfo* pExpr =
tscExprInsert(pQueryInfo, 0, TSDB_FUNC_BLKINFO, &index, resType, bytes, getNewResColId(pCmd), bytes, 0);
tstrncpy(pExpr->base.aliasName, s.name, sizeof(pExpr->base.aliasName));
SExprInfo* pExpr = SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
tscExprInsert(pQueryInfo, 0, TSDB_FUNC_BLKINFO, &index, resType, bytes, getNewResColId(pCmd), bytes, 0); insertResultField(pQueryInfo, 0, &ids, bytes, s.type, s.name, pExpr);
tstrncpy(pExpr->base.aliasName, s.name, sizeof(pExpr->base.aliasName));
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex); pExpr->base.numOfParams = 1;
insertResultField(pQueryInfo, 0, &ids, bytes, s.type, s.name, pExpr); pExpr->base.param[0].i64 = pTableMetaInfo->pTableMeta->tableInfo.rowSize;
pExpr->base.param[0].nType = TSDB_DATA_TYPE_BIGINT;
pExpr->base.numOfParams = 1; return TSDB_CODE_SUCCESS;
pExpr->base.param[0].i64 = pTableMetaInfo->pTableMeta->tableInfo.rowSize; }
pExpr->base.param[0].nType = TSDB_DATA_TYPE_BIGINT;
return TSDB_CODE_SUCCESS; case TSDB_FUNC_HISTOGRAM: {
// check params
if (taosArrayGetSize(pItem->pNode->Expr.paramList) != 4) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg19);
} }
case TSDB_FUNC_HISTOGRAM: { tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0);
// check params if (pParamElem->pNode->tokenId != TK_ID) {
if (taosArrayGetSize(pItem->pNode->Expr.paramList) != 4) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg19); }
}
tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0); SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (pParamElem->pNode->tokenId != TK_ID) { if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) !=
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); TSDB_CODE_SUCCESS) {
} return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
TSDB_CODE_SUCCESS) { }
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
}
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); if (!IS_NUMERIC_TYPE(pSchema->type)) {
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
if (!IS_NUMERIC_TYPE(pSchema->type)) { // bin_type param
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); if (pParamElem[1].pNode->tokenId == TK_ID) {
} return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
// bin_type param tVariant* pVariant = &pParamElem[1].pNode->value;
if (pParamElem[1].pNode->tokenId == TK_ID) { if (pVariant == NULL || pVariant->nType != TSDB_DATA_TYPE_BINARY) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
tVariant* pVariant = &pParamElem[1].pNode->value; #define USER_INPUT_BIN 0
if (pVariant == NULL || pVariant->nType != TSDB_DATA_TYPE_BINARY) { #define LINEAR_BIN 1
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); #define LOG_BIN 2
} int8_t binType;
if (strcasecmp(pVariant->pz, "user_input") == 0) {
binType = USER_INPUT_BIN;
} else if (strcasecmp(pVariant->pz, "linear_bin") == 0) {
binType = LINEAR_BIN;
} else if (strcasecmp(pVariant->pz, "log_bin") == 0) {
binType = LOG_BIN;
} else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg20);
}
// bin_description param in JSON format
if (pParamElem[2].pNode->tokenId == TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
#define USER_INPUT_BIN 0 pVariant = &pParamElem[2].pNode->value;
#define LINEAR_BIN 1 if (pVariant == NULL && pVariant->nType != TSDB_DATA_TYPE_BINARY) {
#define LOG_BIN 2 return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
int8_t binType;
if (strcasecmp(pVariant->pz, "user_input") == 0) {
binType = USER_INPUT_BIN;
} else if (strcasecmp(pVariant->pz, "linear_bin") == 0) {
binType = LINEAR_BIN;
} else if (strcasecmp(pVariant->pz, "log_bin") == 0) {
binType = LOG_BIN;
} else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg20);
}
// bin_description param in JSON format
if (pParamElem[2].pNode->tokenId == TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
pVariant = &pParamElem[2].pNode->value; cJSON* binDesc = cJSON_Parse(pVariant->pz);
if (pVariant == NULL && pVariant->nType != TSDB_DATA_TYPE_BINARY) { int32_t counter;
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); int32_t numBins;
int32_t numOutput;
double* intervals;
if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
int32_t numOfParams = cJSON_GetArraySize(binDesc);
int32_t startIndex;
if (numOfParams != 4) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
} }
cJSON* binDesc = cJSON_Parse(pVariant->pz); cJSON* start = cJSON_GetObjectItem(binDesc, "start");
int32_t counter; cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
int32_t numBins; cJSON* width = cJSON_GetObjectItem(binDesc, "width");
int32_t numOutput; cJSON* count = cJSON_GetObjectItem(binDesc, "count");
double* intervals; cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
int32_t numOfParams = cJSON_GetArraySize(binDesc);
int32_t startIndex;
if (numOfParams != 4) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
}
cJSON* start = cJSON_GetObjectItem(binDesc, "start");
cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
cJSON* width = cJSON_GetObjectItem(binDesc, "width");
cJSON* count = cJSON_GetObjectItem(binDesc, "count");
cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) { if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
} }
if (count->valueint <= 0 || count->valueint > 1000) { if (count->valueint <= 0 || count->valueint > 1000) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg25); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg25);
} }
if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) || if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
(factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) { (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23);
} }
counter = (int32_t)count->valueint; counter = (int32_t)count->valueint;
if (infinity->valueint == false) { if (infinity->valueint == false) {
startIndex = 0; startIndex = 0;
numBins = counter + 1; numBins = counter + 1;
} else { } else {
startIndex = 1; startIndex = 1;
numBins = counter + 3; numBins = counter + 3;
} }
intervals = tcalloc(numBins, sizeof(double)); intervals = tcalloc(numBins, sizeof(double));
if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) { if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
// linear bin process // linear bin process
if (width->valuedouble == 0) { if (width->valuedouble == 0) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg24);
}
for (int i = 0; i < counter + 1; ++i) {
intervals[startIndex] = start->valuedouble + i * width->valuedouble;
if (isinf(intervals[startIndex])) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23);
}
startIndex++;
}
} else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
// log bin process
if (start->valuedouble == 0) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg26);
}
if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg27);
}
for (int i = 0; i < counter + 1; ++i) {
intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
if (isinf(intervals[startIndex])) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23);
}
startIndex++;
}
} else {
tfree(intervals); tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg24);
} }
for (int i = 0; i < counter + 1; ++i) {
if (infinity->valueint == true) { intervals[startIndex] = start->valuedouble + i * width->valuedouble;
intervals[0] = -DBL_MAX; if (isinf(intervals[startIndex])) {
intervals[numBins - 1] = DBL_MAX;
if (isinf(intervals[0]) || isinf(intervals[numBins - 1])) {
tfree(intervals); tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23);
} }
// in case of desc bin orders, -inf/inf should be swapped startIndex++;
assert(numBins >= 4);
if (intervals[1] > intervals[numBins - 2]) {
SWAP(intervals[0], intervals[numBins - 1], double);
}
} }
} else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
} else if (cJSON_IsArray(binDesc)) { /* user input bins */ // log bin process
if (binType != USER_INPUT_BIN) { if (start->valuedouble == 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22); tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg26);
} }
counter = numBins = cJSON_GetArraySize(binDesc); if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
intervals = tcalloc(numBins, sizeof(double));
cJSON* bin = binDesc->child;
if (bin == NULL) {
tfree(intervals); tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg27);
} }
int i = 0; for (int i = 0; i < counter + 1; ++i) {
while (bin) { intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
intervals[i] = bin->valuedouble; if (isinf(intervals[startIndex])) {
if (!cJSON_IsNumber(bin)) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
}
if (i != 0 && intervals[i] <= intervals[i - 1]) {
tfree(intervals); tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23);
} }
bin = bin->next; startIndex++;
i++;
} }
} else { } else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg21); tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
} }
int16_t resultType = pSchema->type; if (infinity->valueint == true) {
int32_t resultSize = pSchema->bytes; intervals[0] = -DBL_MAX;
int32_t interResult = 0; intervals[numBins - 1] = DBL_MAX;
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, counter, &resultType, &resultSize, &interResult, 0, if (isinf(intervals[0]) || isinf(intervals[numBins - 1])) {
false, pUdfInfo); tfree(intervals);
SExprInfo* pExpr = NULL; return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg23);
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd), interResult, }
false); // in case of desc bin orders, -inf/inf should be swapped
numOutput = numBins - 1; assert(numBins >= 4);
tscExprAddParams(&pExpr->base, (char*)&numOutput, TSDB_DATA_TYPE_INT, sizeof(int32_t)); if (intervals[1] > intervals[numBins - 2]) {
tscExprAddParams(&pExpr->base, (char*)intervals, TSDB_DATA_TYPE_BINARY, sizeof(double) * numBins); SWAP(intervals[0], intervals[numBins - 1], double);
tfree(intervals); }
// normalized param
char val[8] = {0};
if (pParamElem[3].pNode->tokenId == TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
pVariant = &pParamElem[3].pNode->value; } else if (cJSON_IsArray(binDesc)) { /* user input bins */
if (pVariant == NULL || pVariant->nType != TSDB_DATA_TYPE_BIGINT || if (binType != USER_INPUT_BIN) {
(pVariant->i64 != 0 && pVariant->i64 != 1)) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
counter = numBins = cJSON_GetArraySize(binDesc);
if (tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true) < 0) { intervals = tcalloc(numBins, sizeof(double));
return TSDB_CODE_TSC_INVALID_OPERATION; cJSON* bin = binDesc->child;
if (bin == NULL) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
} }
int i = 0;
while (bin) {
intervals[i] = bin->valuedouble;
if (!cJSON_IsNumber(bin)) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
}
if (i != 0 && intervals[i] <= intervals[i - 1]) {
tfree(intervals);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg22);
}
bin = bin->next;
i++;
}
} else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg21);
}
int16_t resultType = pSchema->type;
int32_t resultSize = pSchema->bytes;
int32_t interResult = 0;
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, counter, &resultType, &resultSize, &interResult, 0,
false, pUdfInfo);
SExprInfo* pExpr = NULL;
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd), interResult,
false);
numOutput = numBins - 1;
tscExprAddParams(&pExpr->base, (char*)&numOutput, TSDB_DATA_TYPE_INT, sizeof(int32_t));
tscExprAddParams(&pExpr->base, (char*)intervals, TSDB_DATA_TYPE_BINARY, sizeof(double) * numBins);
tfree(intervals);
// normalized param
char val[8] = {0};
if (pParamElem[3].pNode->tokenId == TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, LONG_BYTES); pVariant = &pParamElem[3].pNode->value;
if (pVariant == NULL || pVariant->nType != TSDB_DATA_TYPE_BIGINT ||
(pVariant->i64 != 0 && pVariant->i64 != 1)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName)); if (tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true) < 0) {
getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1); return TSDB_CODE_TSC_INVALID_OPERATION;
// todo refactor: tscColumnListInsert part }
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
if (finalResult) { tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, LONG_BYTES);
insertResultField(pQueryInfo, colIndex, &ids, resultSize, (int8_t)resultType, pExpr->base.aliasName, pExpr);
} else {
assert(ids.num == 1);
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
}
tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid); memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName));
return TSDB_CODE_SUCCESS; getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1);
// todo refactor: tscColumnListInsert part
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
if (finalResult) {
insertResultField(pQueryInfo, colIndex, &ids, resultSize, (int8_t)resultType, pExpr->base.aliasName, pExpr);
} else {
assert(ids.num == 1);
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
} }
default: { tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid);
assert(!TSDB_FUNC_IS_SCALAR(functionId)); return TSDB_CODE_SUCCESS;
pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n); }
if (pUdfInfo == NULL) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9);
}
if (pItem->pNode->Expr.paramList == NULL || taosArrayGetSize(pItem->pNode->Expr.paramList) <= 0) { default: {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg13); assert(!TSDB_FUNC_IS_SCALAR(functionId));
} pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
if (pUdfInfo == NULL) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9);
}
tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0); if (pItem->pNode->Expr.paramList == NULL || taosArrayGetSize(pItem->pNode->Expr.paramList) <= 0) {
; return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg13);
if (pParamElem->pNode->tokenId != TK_ID) { }
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
SColumnIndex index = COLUMN_INDEX_INITIALIZER; tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0);
if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != ;
TSDB_CODE_SUCCESS) { if (pParamElem->pNode->tokenId != TK_ID) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { SColumnIndex index = COLUMN_INDEX_INITIALIZER;
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) !=
} TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
// functions can not be applied to tags pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
int32_t inter = 0; // functions can not be applied to tags
int16_t resType = 0; if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
int32_t bytes = 0; return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
getResultDataInfo(TSDB_DATA_TYPE_INT, 4, functionId, 0, &resType, &bytes, &inter, 0, false, pUdfInfo); }
SExprInfo* pExpr = int32_t inter = 0;
tscExprAppend(pQueryInfo, functionId, &index, resType, bytes, getNewResColId(pCmd), inter, false); int16_t resType = 0;
int32_t bytes = 0;
getResultDataInfo(TSDB_DATA_TYPE_INT, 4, functionId, 0, &resType, &bytes, &inter, 0, false, pUdfInfo);
memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName)); SExprInfo* pExpr =
getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1); tscExprAppend(pQueryInfo, functionId, &index, resType, bytes, getNewResColId(pCmd), inter, false);
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName));
getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1);
uint64_t uid = pTableMetaInfo->pTableMeta->id.uid; SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
if (finalResult) { uint64_t uid = pTableMetaInfo->pTableMeta->id.uid;
insertResultField(pQueryInfo, colIndex, &ids, pUdfInfo->resBytes, pUdfInfo->resType, pExpr->base.aliasName, SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
pExpr); if (finalResult) {
} else { insertResultField(pQueryInfo, colIndex, &ids, pUdfInfo->resBytes, pUdfInfo->resType, pExpr->base.aliasName,
for (int32_t i = 0; i < ids.num; ++i) { pExpr);
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, uid, pSchema); } else {
} for (int32_t i = 0; i < ids.num; ++i) {
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, uid, pSchema);
} }
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
return TSDB_CODE_SUCCESS;
} }
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
return TSDB_CODE_SUCCESS;
} }
return TSDB_CODE_TSC_INVALID_OPERATION;
} }
return TSDB_CODE_TSC_INVALID_OPERATION;
} }
// todo refactor // todo refactor
static SColumnList createColumnList(int32_t num, int16_t tableIndex, int32_t columnIndex) { static SColumnList createColumnList(int32_t num, int16_t tableIndex, int32_t columnIndex) {
......
...@@ -202,7 +202,7 @@ typedef struct SQLFunctionCtx { ...@@ -202,7 +202,7 @@ typedef struct SQLFunctionCtx {
SPoint1 start; SPoint1 start;
SPoint1 end; SPoint1 end;
int32_t maxUniqueResult; SHashObj *pUniqueSet; // for unique function
} SQLFunctionCtx; } SQLFunctionCtx;
typedef struct SAggFunctionInfo { typedef struct SAggFunctionInfo {
......
...@@ -78,7 +78,8 @@ typedef struct SDiskbasedResultBuf { ...@@ -78,7 +78,8 @@ typedef struct SDiskbasedResultBuf {
#define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) // in bytes #define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) // in bytes
#define PAGE_INFO_INITIALIZER (SPageDiskInfo){-1, -1} #define PAGE_INFO_INITIALIZER (SPageDiskInfo){-1, -1}
#define MAX_UNIQUE_RESULT_SIZE (1000000) #define MAX_UNIQUE_RESULT_ROWS (10000)
#define MAX_UNIQUE_RESULT_SIZE (1024*1024*20)
/** /**
* create disk-based result buffer * create disk-based result buffer
* @param pResultBuf * @param pResultBuf
......
...@@ -225,19 +225,14 @@ typedef struct{ ...@@ -225,19 +225,14 @@ typedef struct{
typedef struct { typedef struct {
int64_t timestamp; int64_t timestamp;
char * pTags; char data[];
} UniqueUnit; } UniqueUnit;
typedef struct { typedef struct {
SHashObj *pSet;
int32_t num; int32_t num;
char res[]; char res[];
} SUniqueFuncInfo; } SUniqueFuncInfo;
void freeUniqueUnit(void* unit){
tfree(((UniqueUnit *)unit)->pTags);
}
int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type, int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type,
int32_t *bytes, int32_t *interBytes, int16_t extLength, bool isSuperTable, SUdfInfo* pUdfInfo) { int32_t *bytes, int32_t *interBytes, int16_t extLength, bool isSuperTable, SUdfInfo* pUdfInfo) {
if (!isValidDataType(dataType)) { if (!isValidDataType(dataType)) {
...@@ -371,7 +366,13 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI ...@@ -371,7 +366,13 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} else if (functionId == TSDB_FUNC_UNIQUE) { } else if (functionId == TSDB_FUNC_UNIQUE) {
*type = TSDB_DATA_TYPE_BINARY; *type = TSDB_DATA_TYPE_BINARY;
*bytes = (sizeof(SUniqueFuncInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param); int64_t size = sizeof(UniqueUnit) + dataBytes + extLength;
size *= param;
size += sizeof(SUniqueFuncInfo);
if (size > MAX_UNIQUE_RESULT_SIZE){
size = MAX_UNIQUE_RESULT_SIZE;
}
*bytes = size;
*interBytes = *bytes; *interBytes = *bytes;
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
...@@ -498,17 +499,19 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI ...@@ -498,17 +499,19 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
*type = (int16_t)dataType; *type = (int16_t)dataType;
*bytes = dataBytes; *bytes = dataBytes;
size_t size = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; size_t size = sizeof(STopBotInfo) + (sizeof(tValuePair) + extLength) * param;
// the output column may be larger than sizeof(STopBotInfo) // the output column may be larger than sizeof(STopBotInfo)
*interBytes = (int32_t)size; *interBytes = (int32_t)size;
} else if (functionId == TSDB_FUNC_UNIQUE) { } else if (functionId == TSDB_FUNC_UNIQUE) {
*type = (int16_t)dataType; *type = (int16_t)dataType;
*bytes = dataBytes; *bytes = dataBytes;
int64_t size = sizeof(UniqueUnit) + dataBytes + extLength;
size_t size = sizeof(SUniqueFuncInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; size *= param;
size += sizeof(SUniqueFuncInfo);
// the output column may be larger than sizeof(STopBotInfo) if (size > MAX_UNIQUE_RESULT_SIZE){
size = MAX_UNIQUE_RESULT_SIZE;
}
*interBytes = (int32_t)size; *interBytes = (int32_t)size;
} else if (functionId == TSDB_FUNC_SAMPLE) { } else if (functionId == TSDB_FUNC_SAMPLE) {
*type = (int16_t)dataType; *type = (int16_t)dataType;
...@@ -5143,87 +5146,19 @@ static void copyUniqueRes(SQLFunctionCtx *pCtx, int32_t type) { ...@@ -5143,87 +5146,19 @@ static void copyUniqueRes(SQLFunctionCtx *pCtx, int32_t type) {
SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
SUniqueFuncInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo); SUniqueFuncInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo);
size_t size = sizeof(tValuePair) + pCtx->tagInfo.tagsLen; size_t size = sizeof(UniqueUnit) + pCtx->inputBytes + pCtx->tagInfo.tagsLen;
char *tvp = pRes->res; char *tvp = pRes->res;
int32_t len = (int32_t)(GET_RES_INFO(pCtx)->numOfRes); int32_t len = (int32_t)(GET_RES_INFO(pCtx)->numOfRes);
switch (type) { char *tsOutput = pCtx->ptsOutputBuf;
case TSDB_DATA_TYPE_UINT: char *output = pCtx->pOutput;
case TSDB_DATA_TYPE_INT: { for (int32_t i = 0; i < len; ++i) {
int32_t *output = (int32_t *)pCtx->pOutput; memcpy(tsOutput, tvp, sizeof(int64_t));
for (int32_t i = 0; i < len; ++i, output ++) { memcpy(output, tvp + sizeof(UniqueUnit), pCtx->inputBytes);
*output = ((tValuePair *)tvp)->v.i64;
tvp += size;
}
break;
}
case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_TIMESTAMP:{
int64_t *output = (int64_t *)pCtx->pOutput;
for (int32_t i = 0; i < len; ++i, output ++) {
*output = ((tValuePair *)tvp)->v.i64;
tvp += size;
}
break;
}
case TSDB_DATA_TYPE_DOUBLE: {
double *output = (double *)pCtx->pOutput;
for (int32_t i = 0; i < len; ++i, output ++) {
*output = ((tValuePair *)tvp)->v.dKey;
tvp += size;
}
break;
}
case TSDB_DATA_TYPE_FLOAT: {
float *output = (float *)pCtx->pOutput;
for (int32_t i = 0; i < len; ++i, output ++) {
*output = ((tValuePair *)tvp)->v.dKey;
tvp += size;
}
break;
}
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_SMALLINT: {
int16_t *output = (int16_t *)pCtx->pOutput;
for (int32_t i = 0; i < len; ++i, output ++) {
*output = ((tValuePair *)tvp)->v.i64;
tvp += size;
}
break;
}
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_BOOL:{
int8_t *output = (int8_t *)pCtx->pOutput;
for (int32_t i = 0; i < len; ++i, output ++) {
*output = ((tValuePair *)tvp)->v.i64;
tvp += size;
}
break;
}
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR: {
char *output = pCtx->pOutput;
for (int32_t i = 0; i < len; ++i, output += pCtx->outputBytes) {
*output = ((tValuePair *)tvp)->v.i64;
memcpy(output, ((tValuePair *)tvp)->v.pz, ((tValuePair *)tvp)->v.nLen);
tvp += size;
}
break;
}
default: {
qError("unique function not support data type:%d", pCtx->inputType);
return;
}
}
// set the output timestamp of each record.
TSKEY *output = pCtx->ptsOutputBuf;
for (int32_t i = 0; i < len; ++i, output ++) {
*output = ((tValuePair *)tvp)->timestamp;
tvp += size; tvp += size;
tsOutput += sizeof(int64_t);
output += pCtx->inputBytes;
} }
// set the corresponding tag data for each record // set the corresponding tag data for each record
...@@ -5237,14 +5172,15 @@ static void copyUniqueRes(SQLFunctionCtx *pCtx, int32_t type) { ...@@ -5237,14 +5172,15 @@ static void copyUniqueRes(SQLFunctionCtx *pCtx, int32_t type) {
pData[i] = pCtx->tagInfo.pTagCtxList[i]->pOutput; pData[i] = pCtx->tagInfo.pTagCtxList[i]->pOutput;
} }
for (int32_t i = 0; i < len; ++i, output ++) { tvp = pRes->res;
int16_t offset = 0; for (int32_t i = 0; i < len; ++i) {
int16_t offset = sizeof(UniqueUnit) + pCtx->inputBytes;
for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) { for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) {
memcpy(pData[j], ((tValuePair *)tvp)->pTags + offset, (size_t)pCtx->tagInfo.pTagCtxList[j]->outputBytes); memcpy(pData[j], tvp + offset, (size_t)pCtx->tagInfo.pTagCtxList[j]->outputBytes);
offset += pCtx->tagInfo.pTagCtxList[j]->outputBytes; offset += pCtx->tagInfo.pTagCtxList[j]->outputBytes;
pData[j] += pCtx->tagInfo.pTagCtxList[j]->outputBytes; pData[j] += pCtx->tagInfo.pTagCtxList[j]->outputBytes;
tvp += size;
} }
tvp += size;
} }
tfree(pData); tfree(pData);
...@@ -5254,69 +5190,79 @@ static bool unique_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pRes ...@@ -5254,69 +5190,79 @@ static bool unique_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pRes
if (!function_setup(pCtx, pResInfo)) { if (!function_setup(pCtx, pResInfo)) {
return false; return false;
} }
SUniqueFuncInfo *uniqueInfo = getUniqueOutputInfo(pCtx); SUniqueFuncInfo *uniqueInfo = getUniqueOutputInfo(pCtx);
uniqueInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
taosHashSetFreeFp(uniqueInfo->pSet, freeUniqueUnit);
return true; return true;
} }
static void unique_function(SQLFunctionCtx *pCtx) { static void do_unique_function(SQLFunctionCtx *pCtx, SUniqueFuncInfo *pInfo, TSKEY timestamp, char *pData, char *tag){
SUniqueFuncInfo *pInfo = getUniqueOutputInfo(pCtx); tValuePair *unique = taosHashGet(pCtx->pUniqueSet, pData, pCtx->inputBytes);
if (unique == NULL) {
for (int32_t i = 0; i < pCtx->size; i++) { size_t size = sizeof(UniqueUnit) + pCtx->inputBytes + pCtx->tagInfo.tagsLen;
char *pData = GET_INPUT_DATA(pCtx, i); char *tmp = pInfo->res + pInfo->num * size;
TSKEY k = 0; ((UniqueUnit*)tmp)->timestamp = timestamp;
if (pCtx->ptsList != NULL) { char *data = tmp + sizeof(UniqueUnit);
k = GET_TS_DATA(pCtx, i); char *tags = tmp + sizeof(UniqueUnit) + pCtx->inputBytes;
} memcpy(data, pData, pCtx->inputBytes);
tValuePair *unique = taosHashGet(pInfo->pSet, pData, pCtx->inputBytes);
if (unique == NULL) {
size_t size = sizeof(tValuePair) + pCtx->tagInfo.tagsLen;
tValuePair *tmp = (tValuePair *)(pInfo->res + pInfo->num * size);
if (pCtx->inputType == TSDB_DATA_TYPE_BINARY || pCtx->inputType == TSDB_DATA_TYPE_NCHAR) {
tVariantCreateFromBinary(&tmp->v, varDataVal(pData), varDataLen(pData), pCtx->inputType);
}else{
tVariantCreateFromBinary(&tmp->v, pData, 0, pCtx->inputType);
}
tmp->timestamp = k;
if (pCtx->currentStage == MERGE_STAGE && tag != NULL) {
memcpy(tags, tag, (size_t)pCtx->tagInfo.tagsLen);
}else{
int32_t offset = 0; int32_t offset = 0;
for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) { for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) {
SQLFunctionCtx *tagCtx = pCtx->tagInfo.pTagCtxList[j]; SQLFunctionCtx *tagCtx = pCtx->tagInfo.pTagCtxList[j];
if (tagCtx->functionId == TSDB_FUNC_TAG_DUMMY) { if (tagCtx->functionId == TSDB_FUNC_TAG_DUMMY) {
aAggs[TSDB_FUNC_TAG].xFunction(tagCtx); aAggs[TSDB_FUNC_TAG].xFunction(tagCtx);
memcpy(tmp->pTags + offset, tagCtx->pOutput, tagCtx->outputBytes); memcpy(tags + offset, tagCtx->pOutput, tagCtx->outputBytes);
offset += tagCtx->outputBytes; offset += tagCtx->outputBytes;
} }
} }
}
taosHashPut(pCtx->pUniqueSet, pData, pCtx->inputBytes, &tmp, sizeof(tValuePair*));
pInfo->num++;
}else if(unique->timestamp > timestamp){
unique->timestamp = timestamp;
}
}
static void unique_function(SQLFunctionCtx *pCtx) {
SUniqueFuncInfo *pInfo = getUniqueOutputInfo(pCtx);
taosHashPut(pInfo->pSet, pData, pCtx->inputBytes, &tmp, sizeof(tValuePair*)); for (int32_t i = 0; i < pCtx->size; i++) {
pInfo->num++; char *pData = GET_INPUT_DATA(pCtx, i);
}else if(unique->timestamp > k){ TSKEY k = 0;
unique->timestamp = k; if (pCtx->ptsList != NULL) {
k = GET_TS_DATA(pCtx, i);
}
do_unique_function(pCtx, pInfo, k, pData, NULL);
if (sizeof(SUniqueFuncInfo) + pInfo->num * (sizeof(UniqueUnit) + pCtx->inputBytes + pCtx->tagInfo.tagsLen) >= MAX_UNIQUE_RESULT_SIZE){
GET_RES_INFO(pCtx)->numOfRes = -1; // mark out of memory
return;
} }
} }
GET_RES_INFO(pCtx)->numOfRes = 1;
} }
static void unique_function_merge(SQLFunctionCtx *pCtx) { static void unique_function_merge(SQLFunctionCtx *pCtx) {
//SUniqueFuncInfo *pInput = (SUniqueFuncInfo *)GET_INPUT_DATA_LIST(pCtx); SUniqueFuncInfo *pInput = (SUniqueFuncInfo *)GET_INPUT_DATA_LIST(pCtx);
//SUniqueFuncInfo *pOutput = getUniqueOutputInfo(pCtx); SUniqueFuncInfo *pOutput = getUniqueOutputInfo(pCtx);
// the intermediate result is binary, we only use the output data type size_t size = sizeof(UniqueUnit) + pCtx->inputBytes + pCtx->tagInfo.tagsLen;
// for (int32_t i = 0; i < pInput->num; ++i) { for (int32_t i = 0; i < pInput->num; ++i) {
// int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT)? TSDB_DATA_TYPE_DOUBLE:pCtx->outputType; char *tmp = pInput->res + i* size;
// do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64, &pInput->res[i]->v.i64, pInput->res[i]->timestamp, TSKEY timestamp = ((UniqueUnit*)tmp)->timestamp;
// type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); char *data = tmp + sizeof(UniqueUnit);
// } char *tags = tmp + sizeof(UniqueUnit) + pCtx->inputBytes;
// do_unique_function(pCtx, pOutput, timestamp, data, tags);
// SET_VAL(pCtx, pInput->num, pOutput->num);
// if (sizeof(SUniqueFuncInfo) + pOutput->num * (sizeof(UniqueUnit) + pCtx->inputBytes + pCtx->tagInfo.tagsLen) >= MAX_UNIQUE_RESULT_SIZE){
// if (pOutput->num > 0) { GET_RES_INFO(pCtx)->numOfRes = -1; // mark out of memory
// SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); return;
// pResInfo->hasResult = DATA_SET_FLAG; }
// } }
GET_RES_INFO(pCtx)->numOfRes = pOutput->num;
} }
static void unique_func_finalizer(SQLFunctionCtx *pCtx) { static void unique_func_finalizer(SQLFunctionCtx *pCtx) {
...@@ -5328,7 +5274,6 @@ static void unique_func_finalizer(SQLFunctionCtx *pCtx) { ...@@ -5328,7 +5274,6 @@ static void unique_func_finalizer(SQLFunctionCtx *pCtx) {
doFinalizer(pCtx); doFinalizer(pCtx);
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
/* /*
* function compatible list. * function compatible list.
......
...@@ -356,7 +356,13 @@ SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numO ...@@ -356,7 +356,13 @@ SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numO
idata.info.bytes = pExpr[i].base.resBytes; idata.info.bytes = pExpr[i].base.resBytes;
idata.info.colId = pExpr[i].base.resColId; idata.info.colId = pExpr[i].base.resColId;
int32_t size = MAX(idata.info.bytes * numOfRows, minSize); int64_t tmp = idata.info.bytes;
tmp *= numOfRows;
if (tmp >= 1024*1024*1024) { // 1G
qError("size is too large, failed to allocate column buffer for output buffer");
goto _clean;
}
int32_t size = MAX(tmp, minSize);
idata.pData = calloc(1, size); // at least to hold a pointer on x64 platform idata.pData = calloc(1, size); // at least to hold a pointer on x64 platform
if (idata.pData == NULL) { if (idata.pData == NULL) {
qError("failed to allocate column buffer for output buffer"); qError("failed to allocate column buffer for output buffer");
...@@ -1003,10 +1009,10 @@ static void doApplyFunctions(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx ...@@ -1003,10 +1009,10 @@ static void doApplyFunctions(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx
} }
} }
if (functionId == TSDB_FUNC_UNIQUE && GET_RES_INFO(&(pCtx[k]))->numOfRes > pQueryAttr->maxUniqueResult){ if (functionId == TSDB_FUNC_UNIQUE &&
(GET_RES_INFO(&(pCtx[k]))->numOfRes > MAX_UNIQUE_RESULT_ROWS || GET_RES_INFO(&(pCtx[k]))->numOfRes == -1)){
qError("Unique result num is too large. num: %d, limit: %d", qError("Unique result num is too large. num: %d, limit: %d",
GET_RES_INFO(&(pCtx[k]))->numOfRes, pQueryAttr->maxUniqueResult); GET_RES_INFO(&(pCtx[k]))->numOfRes, MAX_UNIQUE_RESULT_ROWS);
aAggs[functionId].xFinalize(&pCtx[k]);
longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_UNIQUE_RESULT_TOO_LARGE); longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_UNIQUE_RESULT_TOO_LARGE);
} }
...@@ -1271,10 +1277,10 @@ static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunction ...@@ -1271,10 +1277,10 @@ static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunction
} }
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
if (functionId == TSDB_FUNC_UNIQUE && GET_RES_INFO(&(pCtx[k]))->numOfRes > pQueryAttr->maxUniqueResult){ if (functionId == TSDB_FUNC_UNIQUE &&
(GET_RES_INFO(&(pCtx[k]))->numOfRes > MAX_UNIQUE_RESULT_ROWS || GET_RES_INFO(&(pCtx[k]))->numOfRes == -1)){
qError("Unique result num is too large. num: %d, limit: %d", qError("Unique result num is too large. num: %d, limit: %d",
GET_RES_INFO(&(pCtx[k]))->numOfRes, pQueryAttr->maxUniqueResult); GET_RES_INFO(&(pCtx[k]))->numOfRes, MAX_UNIQUE_RESULT_ROWS);
aAggs[functionId].xFinalize(&pCtx[k]);
longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_UNIQUE_RESULT_TOO_LARGE); longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_UNIQUE_RESULT_TOO_LARGE);
} }
} }
...@@ -1976,9 +1982,6 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr ...@@ -1976,9 +1982,6 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr
pCtx->end.key = INT64_MIN; pCtx->end.key = INT64_MIN;
pCtx->startTs = INT64_MIN; pCtx->startTs = INT64_MIN;
if (pCtx->functionId == TSDB_FUNC_UNIQUE){
pCtx->maxUniqueResult = pQueryAttr->maxUniqueResult;
}
pCtx->numOfParams = pSqlExpr->numOfParams; pCtx->numOfParams = pSqlExpr->numOfParams;
for (int32_t j = 0; j < pCtx->numOfParams; ++j) { for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
int16_t type = pSqlExpr->param[j].nType; int16_t type = pSqlExpr->param[j].nType;
...@@ -2028,6 +2031,8 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr ...@@ -2028,6 +2031,8 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr
pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT; pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
} else if (functionId == TSDB_FUNC_SCALAR_EXPR) { } else if (functionId == TSDB_FUNC_SCALAR_EXPR) {
pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i]; pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i];
} else if (functionId == TSDB_FUNC_UNIQUE){
pCtx->pUniqueSet = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
} }
} }
...@@ -2052,6 +2057,9 @@ static void* destroySQLFunctionCtx(SQLFunctionCtx* pCtx, int32_t numOfOutput) { ...@@ -2052,6 +2057,9 @@ static void* destroySQLFunctionCtx(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
tVariantDestroy(&pCtx[i].tag); tVariantDestroy(&pCtx[i].tag);
tfree(pCtx[i].tagInfo.pTagCtxList); tfree(pCtx[i].tagInfo.pTagCtxList);
if (pCtx[i].functionId == TSDB_FUNC_UNIQUE){
taosHashClear(pCtx[i].pUniqueSet);
}
} }
tfree(pCtx); tfree(pCtx);
...@@ -2771,15 +2779,7 @@ static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, i ...@@ -2771,15 +2779,7 @@ static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, i
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
int32_t MIN_ROWS_PER_PAGE = 4; int32_t MIN_ROWS_PER_PAGE = 4;
if (pQueryAttr->uniqueQuery) { *rowsize = (int32_t)(pQueryAttr->resultRowSize * getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
int64_t rowSize = pQueryAttr->resultRowSize;
while(rowSize*pQueryAttr->maxUniqueResult > 1024*1024*100){
pQueryAttr->maxUniqueResult = pQueryAttr->maxUniqueResult >> 1u;
}
*rowsize = (int32_t)(rowSize*pQueryAttr->maxUniqueResult);
}else{
*rowsize = (int32_t)(pQueryAttr->resultRowSize * getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
}
int32_t overhead = sizeof(tFilePage); int32_t overhead = sizeof(tFilePage);
// one page contains at least two rows // one page contains at least two rows
...@@ -8994,7 +8994,7 @@ static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SCol ...@@ -8994,7 +8994,7 @@ static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SCol
for (int32_t i = 0; i < numOfOutput; ++i) { for (int32_t i = 0; i < numOfOutput; ++i) {
int16_t functId = pExprs[i].base.functionId; int16_t functId = pExprs[i].base.functionId;
if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM || functId == TSDB_FUNC_SAMPLE) { if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM || functId == TSDB_FUNC_SAMPLE || funcIf == TSDB_FUNC_UNIQUE) {
int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols); int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
if (j < 0 || j >= pTableInfo->numOfCols) { if (j < 0 || j >= pTableInfo->numOfCols) {
return TSDB_CODE_QRY_INVALID_MSG; return TSDB_CODE_QRY_INVALID_MSG;
...@@ -9580,7 +9580,6 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S ...@@ -9580,7 +9580,6 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S
pQueryAttr->pFilters = pFilters; pQueryAttr->pFilters = pFilters;
pQueryAttr->range = pQueryMsg->range; pQueryAttr->range = pQueryMsg->range;
pQueryAttr->uniqueQuery = isUniqueQuery(numOfOutput, pExprs); pQueryAttr->uniqueQuery = isUniqueQuery(numOfOutput, pExprs);
pQueryAttr->maxUniqueResult = MAX_UNIQUE_RESULT_SIZE;
pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo)); pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
if (pQueryAttr->tableCols == NULL) { if (pQueryAttr->tableCols == NULL) {
......
...@@ -45,7 +45,7 @@ int32_t getRowNumForMultioutput(SQueryAttr* pQueryAttr, bool topBottomQuery, boo ...@@ -45,7 +45,7 @@ int32_t getRowNumForMultioutput(SQueryAttr* pQueryAttr, bool topBottomQuery, boo
} }
if (pQueryAttr->uniqueQuery){ if (pQueryAttr->uniqueQuery){
return pQueryAttr->maxUniqueResult; return MAX_UNIQUE_RESULT_ROWS;
} }
return 1; return 1;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册