提交 267f2c03 编写于 作者: H hjxilinx

[td-225] fix bugs found in sim script

上级 4c8955f4
...@@ -2969,11 +2969,12 @@ static void tag_project_function(SQLFunctionCtx *pCtx) { ...@@ -2969,11 +2969,12 @@ static void tag_project_function(SQLFunctionCtx *pCtx) {
char* output = pCtx->aOutputBuf; char* output = pCtx->aOutputBuf;
if (pCtx->tag.nType == TSDB_DATA_TYPE_BINARY || pCtx->tag.nType == TSDB_DATA_TYPE_NCHAR) { if (pCtx->tag.nType == TSDB_DATA_TYPE_BINARY || pCtx->tag.nType == TSDB_DATA_TYPE_NCHAR) {
*(int16_t*) output = pCtx->tag.nLen; varDataSetLen(output, pCtx->tag.nLen);
output += VARSTR_HEADER_SIZE; tVariantDump(&pCtx->tag, varDataVal(output), pCtx->outputType);
} else {
tVariantDump(&pCtx->tag, output, pCtx->outputType);
} }
tVariantDump(&pCtx->tag, output, pCtx->outputType);
pCtx->aOutputBuf += pCtx->outputBytes; pCtx->aOutputBuf += pCtx->outputBytes;
} }
} }
......
...@@ -5910,7 +5910,7 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray* ...@@ -5910,7 +5910,7 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray*
} }
if (pSqlExpr->pLeft == NULL) { if (pSqlExpr->pLeft == NULL) {
if (pSqlExpr->nSQLOptr >= TK_TINYINT && pSqlExpr->nSQLOptr <= TK_DOUBLE) { if (pSqlExpr->nSQLOptr >= TK_BOOL && pSqlExpr->nSQLOptr <= TK_STRING) {
*pExpr = calloc(1, sizeof(tExprNode)); *pExpr = calloc(1, sizeof(tExprNode));
(*pExpr)->nodeType = TSQL_NODE_VALUE; (*pExpr)->nodeType = TSQL_NODE_VALUE;
(*pExpr)->pVal = calloc(1, sizeof(tVariant)); (*pExpr)->pVal = calloc(1, sizeof(tVariant));
......
...@@ -1436,8 +1436,8 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO ...@@ -1436,8 +1436,8 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
return; return;
} else { // reach the maximum retry count, abort } else { // reach the maximum retry count, abort
atomic_val_compare_exchange_32(&pState->code, TSDB_CODE_SUCCESS, numOfRows); atomic_val_compare_exchange_32(&pState->code, TSDB_CODE_SUCCESS, numOfRows);
tscError("%p sub:%p retrieve failed,code:%s,orderOfSub:%d failed.no more retry,set global code:%d", pPObj, pSql, tscError("%p sub:%p retrieve failed,code:%s,orderOfSub:%d failed.no more retry,set global code:%s", pPObj, pSql,
numOfRows, subqueryIndex, tstrerror(pState->code)); tstrerror(numOfRows), subqueryIndex, tstrerror(pState->code));
} }
} }
......
...@@ -115,10 +115,8 @@ static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t o ...@@ -115,10 +115,8 @@ static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t o
case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR:
return POINTER_SHIFT(row, *(VarDataOffsetT *)POINTER_SHIFT(row, offset)); return POINTER_SHIFT(row, *(VarDataOffsetT *)POINTER_SHIFT(row, offset));
break;
default: default:
return POINTER_SHIFT(row, offset); return POINTER_SHIFT(row, offset);
break;
} }
} }
......
...@@ -36,6 +36,11 @@ extern "C" { ...@@ -36,6 +36,11 @@ extern "C" {
typedef int32_t VarDataOffsetT; typedef int32_t VarDataOffsetT;
typedef int16_t VarDataLenT; typedef int16_t VarDataLenT;
typedef struct tstr {
VarDataLenT len;
char data[];
} tstr;
#define VARSTR_HEADER_SIZE sizeof(VarDataLenT) #define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
#define varDataLen(v) ((VarDataLenT *)(v))[0] #define varDataLen(v) ((VarDataLenT *)(v))[0]
...@@ -74,10 +79,10 @@ extern const int32_t TYPE_BYTES[11]; ...@@ -74,10 +79,10 @@ extern const int32_t TYPE_BYTES[11];
#define TSDB_DATA_NULL_STR "NULL" #define TSDB_DATA_NULL_STR "NULL"
#define TSDB_DATA_NULL_STR_L "null" #define TSDB_DATA_NULL_STR_L "null"
#define TSDB_TRUE 1 #define TSDB_TRUE 1
#define TSDB_FALSE 0 #define TSDB_FALSE 0
#define TSDB_OK 0 #define TSDB_OK 0
#define TSDB_ERR -1 #define TSDB_ERR -1
#define TS_PATH_DELIMITER "." #define TS_PATH_DELIMITER "."
......
...@@ -102,7 +102,7 @@ int tsdbTableSetSName(STableCfg *config, char *sname, bool dup); ...@@ -102,7 +102,7 @@ int tsdbTableSetSName(STableCfg *config, char *sname, bool dup);
void tsdbClearTableCfg(STableCfg *config); void tsdbClearTableCfg(STableCfg *config);
int32_t tsdbGetTableTagVal(TsdbRepoT *repo, STableId* id, int32_t colId, int16_t *type, int16_t *bytes, char **val); int32_t tsdbGetTableTagVal(TsdbRepoT *repo, STableId* id, int32_t colId, int16_t *type, int16_t *bytes, char **val);
int32_t tsdbGetTableName(TsdbRepoT *repo, STableId* id, char** name); char* tsdbGetTableName(TsdbRepoT *repo, const STableId* id, int16_t* bytes);
int tsdbCreateTable(TsdbRepoT *repo, STableCfg *pCfg); int tsdbCreateTable(TsdbRepoT *repo, STableCfg *pCfg);
int tsdbDropTable(TsdbRepoT *pRepo, STableId tableId); int tsdbDropTable(TsdbRepoT *pRepo, STableId tableId);
......
...@@ -552,18 +552,18 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr ...@@ -552,18 +552,18 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
if (cond.start != NULL) { if (cond.start != NULL) {
int32_t optr = cond.start->optr; int32_t optr = cond.start->optr;
if (optr == TSDB_RELATION_EQUAL) { if (optr == TSDB_RELATION_EQUAL) { // equals
while(tSkipListIterNext(iter)) { while(tSkipListIterNext(iter)) {
SSkipListNode* pNode = tSkipListIterGet(iter); SSkipListNode* pNode = tSkipListIterGet(iter);
int32_t ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v); int32_t ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v);
if (ret == 0) { if (ret != 0) {
taosArrayPush(result, SL_GET_NODE_DATA(pNode));
} else {
break; break;
} }
taosArrayPush(result, SL_GET_NODE_DATA(pNode));
} }
} else if (optr == TSDB_RELATION_GREATER || optr == TSDB_RELATION_GREATER_EQUAL) { } else if (optr == TSDB_RELATION_GREATER || optr == TSDB_RELATION_GREATER_EQUAL) { // greater equal
bool comp = true; bool comp = true;
int32_t ret = 0; int32_t ret = 0;
...@@ -582,8 +582,33 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr ...@@ -582,8 +582,33 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
comp = false; comp = false;
} }
} }
} else if (optr == TSDB_RELATION_NOT_EQUAL) { } else if (optr == TSDB_RELATION_NOT_EQUAL) { // not equal
assert(0); bool comp = true;
while(tSkipListIterNext(iter)) {
SSkipListNode* pNode = tSkipListIterGet(iter);
comp = comp && (pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v) == 0);
if (comp) {
continue;
}
taosArrayPush(result, SL_GET_NODE_DATA(pNode));
}
tSkipListDestroyIter(iter);
comp = true;
iter = tSkipListCreateIterFromVal(pSkipList, (char*) cond.start->v, pSkipList->keyInfo.type, TSDB_ORDER_DESC);
while(tSkipListIterNext(iter)) {
SSkipListNode* pNode = tSkipListIterGet(iter);
comp = comp && (pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v) == 0);
if (comp) {
continue;
}
taosArrayPush(result, SL_GET_NODE_DATA(pNode));
}
} else { } else {
assert(0); assert(0);
} }
...@@ -773,8 +798,6 @@ static void tSQLBinaryTraverseOnSkipList(tExprNode *pExpr, SArray *pResult, SSki ...@@ -773,8 +798,6 @@ static void tSQLBinaryTraverseOnSkipList(tExprNode *pExpr, SArray *pResult, SSki
tSkipListDestroyIter(iter); tSkipListDestroyIter(iter);
} }
static void tQueryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArray* result) { static void tQueryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArray* result) {
SSkipListIterator* iter = tSkipListCreateIter(pSkipList); SSkipListIterator* iter = tSkipListCreateIter(pSkipList);
...@@ -785,7 +808,7 @@ static void tQueryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, ...@@ -785,7 +808,7 @@ static void tQueryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo,
char* pTable = SL_GET_NODE_DATA(pNode); char* pTable = SL_GET_NODE_DATA(pNode);
//todo refactor: //todo refactor:
char* name = (*(STable**) pTable)->name; tstr* name = ((STableIndexElem*) pTable)->pTable->name;
// char* name = NULL; // char* name = NULL;
// tsdbGetTableName(tsdb, pTable, &name); // tsdbGetTableName(tsdb, pTable, &name);
......
...@@ -428,9 +428,10 @@ static bool hasNullValue(SQuery *pQuery, int32_t col, SDataBlockInfo *pDataBlock ...@@ -428,9 +428,10 @@ static bool hasNullValue(SQuery *pQuery, int32_t col, SDataBlockInfo *pDataBlock
return false; return false;
} }
*pColStatis = NULL;
if (pStatis != NULL) { if (pStatis != NULL) {
*pColStatis = getStatisInfo(pQuery, pStatis, pDataBlockInfo, col); *pColStatis = getStatisInfo(pQuery, pStatis, pDataBlockInfo, col);
} else {
*pColStatis = NULL;
} }
if ((*pColStatis) != NULL && (*pColStatis)->numOfNull == 0) { if ((*pColStatis) != NULL && (*pColStatis)->numOfNull == 0) {
...@@ -820,7 +821,21 @@ static TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) { ...@@ -820,7 +821,21 @@ static TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
return ekey; return ekey;
} }
char *getDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas, int32_t col, int32_t size, //todo binary search
static void* getDataBlockImpl(SArray* pDataBlock, int32_t colId) {
int32_t numOfCols = taosArrayGetSize(pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData *p = taosArrayGet(pDataBlock, i);
if (colId == p->info.colId) {
return p->pData;
}
}
return NULL;
}
static char *getDataBlock(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas, int32_t col, int32_t size,
SArray *pDataBlock) { SArray *pDataBlock) {
char *dataBlock = NULL; char *dataBlock = NULL;
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
...@@ -867,20 +882,7 @@ char *getDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas, int3 ...@@ -867,20 +882,7 @@ char *getDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas, int3
if (TSDB_COL_IS_TAG(pCol->flag) || pDataBlock == NULL) { if (TSDB_COL_IS_TAG(pCol->flag) || pDataBlock == NULL) {
dataBlock = NULL; dataBlock = NULL;
} else { } else {
/* dataBlock = getDataBlockImpl(pDataBlock, pCol->colId);
* the colIndex is acquired from the first meter of all qualified meters in this vnode during query prepare
* stage, the remain meter may not have the required column in cache actually. So, the validation of required
* column in cache with the corresponding meter schema is reinforced.
*/
int32_t numOfCols = taosArrayGetSize(pDataBlock);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumnInfoData *p = taosArrayGet(pDataBlock, i);
if (pCol->colId == p->info.colId) {
dataBlock = p->pData;
break;
}
}
} }
} }
...@@ -919,7 +921,7 @@ static void blockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis * ...@@ -919,7 +921,7 @@ static void blockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *
SDataStatis *tpField = NULL; SDataStatis *tpField = NULL;
bool hasNull = hasNullValue(pQuery, k, pDataBlockInfo, pStatis, &tpField); bool hasNull = hasNullValue(pQuery, k, pDataBlockInfo, pStatis, &tpField);
char *dataBlock = getDataBlocks(pRuntimeEnv, &sasArray[k], k, pDataBlockInfo->rows, pDataBlock); char *dataBlock = getDataBlock(pRuntimeEnv, &sasArray[k], k, pDataBlockInfo->rows, pDataBlock);
setExecParams(pQuery, &pCtx[k], dataBlock, primaryKeyCol, pDataBlockInfo->rows, functionId, tpField, hasNull, setExecParams(pQuery, &pCtx[k], dataBlock, primaryKeyCol, pDataBlockInfo->rows, functionId, tpField, hasNull,
&sasArray[k], pRuntimeEnv->scanFlag); &sasArray[k], pRuntimeEnv->scanFlag);
...@@ -1134,7 +1136,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1134,7 +1136,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
SDataStatis *pColStatis = NULL; SDataStatis *pColStatis = NULL;
bool hasNull = hasNullValue(pQuery, k, pDataBlockInfo, pStatis, &pColStatis); bool hasNull = hasNullValue(pQuery, k, pDataBlockInfo, pStatis, &pColStatis);
char *dataBlock = getDataBlocks(pRuntimeEnv, &sasArray[k], k, pDataBlockInfo->rows, pDataBlock); char *dataBlock = getDataBlock(pRuntimeEnv, &sasArray[k], k, pDataBlockInfo->rows, pDataBlock);
setExecParams(pQuery, &pCtx[k], dataBlock, primaryKeyCol, pDataBlockInfo->rows, functionId, pColStatis, hasNull, setExecParams(pQuery, &pCtx[k], dataBlock, primaryKeyCol, pDataBlockInfo->rows, functionId, pColStatis, hasNull,
&sasArray[k], pRuntimeEnv->scanFlag); &sasArray[k], pRuntimeEnv->scanFlag);
...@@ -1143,7 +1145,8 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1143,7 +1145,8 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
// set the input column data // set the input column data
for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) { for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k]; SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
pFilterInfo->pData = getDataBlocks(pRuntimeEnv, &sasArray[k], pFilterInfo->info.colId, pDataBlockInfo->rows, pDataBlock); pFilterInfo->pData = getDataBlockImpl(pDataBlock, pFilterInfo->info.colId);
assert(pFilterInfo->pData != NULL);
} }
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
...@@ -1157,10 +1160,10 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1157,10 +1160,10 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
} }
int32_t j = 0; int32_t j = 0;
TSKEY lastKey = -1; int32_t offset = -1;
for (j = 0; j < pDataBlockInfo->rows; ++j) { for (j = 0; j < pDataBlockInfo->rows; ++j) {
int32_t offset = GET_COL_DATA_POS(pQuery, j, step); offset = GET_COL_DATA_POS(pQuery, j, step);
if (pRuntimeEnv->pTSBuf != NULL) { if (pRuntimeEnv->pTSBuf != NULL) {
int32_t r = doTSJoinFilter(pRuntimeEnv, offset); int32_t r = doTSJoinFilter(pRuntimeEnv, offset);
...@@ -1194,7 +1197,6 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1194,7 +1197,6 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
SWindowStatus *pStatus = getTimeWindowResStatus(pWindowResInfo, curTimeWindow(pWindowResInfo)); SWindowStatus *pStatus = getTimeWindowResStatus(pWindowResInfo, curTimeWindow(pWindowResInfo));
doRowwiseApplyFunctions(pRuntimeEnv, pStatus, &win, offset); doRowwiseApplyFunctions(pRuntimeEnv, pStatus, &win, offset);
lastKey = ts;
STimeWindow nextWin = win; STimeWindow nextWin = win;
int32_t index = pWindowResInfo->curIndex; int32_t index = pWindowResInfo->curIndex;
...@@ -1231,9 +1233,6 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1231,9 +1233,6 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
} }
} }
// update the lastKey
lastKey = primaryKeyCol[offset];
// all startOffset are identical // all startOffset are identical
offset -= pCtx[0].startOffset; offset -= pCtx[0].startOffset;
...@@ -1254,7 +1253,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1254,7 +1253,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
} }
} }
pQuery->lastKey = lastKey + step; pQuery->lastKey = primaryKeyCol[offset] + step;
// todo refactor: extract method // todo refactor: extract method
for(int32_t i = 0; i < pQuery->numOfOutput; ++i) { for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
...@@ -2327,7 +2326,7 @@ static void getNextTimeWindow(SQuery *pQuery, STimeWindow *pTimeWindow) { ...@@ -2327,7 +2326,7 @@ static void getNextTimeWindow(SQuery *pQuery, STimeWindow *pTimeWindow) {
pTimeWindow->ekey = pTimeWindow->skey + (pQuery->intervalTime - 1); pTimeWindow->ekey = pTimeWindow->skey + (pQuery->intervalTime - 1);
} }
SArray *loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo, SDataStatis **pStatis) { SArray *loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, void* pQueryHandle, SDataBlockInfo* pBlockInfo, SDataStatis **pStatis) {
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
uint32_t r = 0; uint32_t r = 0;
...@@ -2351,16 +2350,16 @@ SArray *loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBl ...@@ -2351,16 +2350,16 @@ SArray *loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBl
qTrace("QInfo:%p data block ignored, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_QINFO_ADDR(pRuntimeEnv), qTrace("QInfo:%p data block ignored, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_QINFO_ADDR(pRuntimeEnv),
pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
} else if (r == BLK_DATA_FILEDS_NEEDED) { } else if (r == BLK_DATA_FILEDS_NEEDED) {
if (tsdbRetrieveDataBlockStatisInfo(pRuntimeEnv->pQueryHandle, pStatis) != TSDB_CODE_SUCCESS) { if (tsdbRetrieveDataBlockStatisInfo(pQueryHandle, pStatis) != TSDB_CODE_SUCCESS) {
// return DISK_DATA_LOAD_FAILED; // return DISK_DATA_LOAD_FAILED;
} }
if (*pStatis == NULL) { if (*pStatis == NULL) {
pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL);
} }
} else { } else {
assert(r == BLK_DATA_ALL_NEEDED); assert(r == BLK_DATA_ALL_NEEDED);
if (tsdbRetrieveDataBlockStatisInfo(pRuntimeEnv->pQueryHandle, pStatis) != TSDB_CODE_SUCCESS) { if (tsdbRetrieveDataBlockStatisInfo(pQueryHandle, pStatis) != TSDB_CODE_SUCCESS) {
// return DISK_DATA_LOAD_FAILED; // return DISK_DATA_LOAD_FAILED;
} }
...@@ -2376,7 +2375,7 @@ SArray *loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBl ...@@ -2376,7 +2375,7 @@ SArray *loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBl
// return DISK_DATA_DISCARDED; // return DISK_DATA_DISCARDED;
} }
pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL);
} }
return pDataBlock; return pDataBlock;
...@@ -2505,7 +2504,7 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -2505,7 +2504,7 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
} }
SDataStatis *pStatis = NULL; SDataStatis *pStatis = NULL;
SArray * pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, &blockInfo, &pStatis); SArray * pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, pQueryHandle, &blockInfo, &pStatis);
pQuery->pos = QUERY_IS_ASC_QUERY(pQuery) ? 0 : blockInfo.rows - 1; pQuery->pos = QUERY_IS_ASC_QUERY(pQuery) ? 0 : blockInfo.rows - 1;
int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, binarySearchForKey, int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, binarySearchForKey,
...@@ -2554,17 +2553,17 @@ static void doSetTagValueInParam(void *tsdb, STableId* pTableId, int32_t tagColI ...@@ -2554,17 +2553,17 @@ static void doSetTagValueInParam(void *tsdb, STableId* pTableId, int32_t tagColI
int16_t type = 0; int16_t type = 0;
if (tagColId == TSDB_TBNAME_COLUMN_INDEX) { if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
tsdbGetTableName(tsdb, pTableId, &val); val = tsdbGetTableName(tsdb, pTableId, &bytes);
bytes = strnlen(val, TSDB_TABLE_NAME_LEN);
type = TSDB_DATA_TYPE_BINARY; type = TSDB_DATA_TYPE_BINARY;
tVariantCreateFromBinary(param, varDataVal(val), varDataLen(val), type);
} else { } else {
tsdbGetTableTagVal(tsdb, pTableId, tagColId, &type, &bytes, &val); tsdbGetTableTagVal(tsdb, pTableId, tagColId, &type, &bytes, &val);
}
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
tVariantCreateFromBinary(param, val, bytes, type); tVariantCreateFromBinary(param, varDataVal(val), varDataLen(val), type);
} else {
if (tagColId == TSDB_TBNAME_COLUMN_INDEX) { tVariantCreateFromBinary(param, val, bytes, type);
tfree(val); }
} }
} }
...@@ -3082,11 +3081,6 @@ void resetMergeResultBuf(SQuery *pQuery, SQLFunctionCtx *pCtx, SResultInfo *pRes ...@@ -3082,11 +3081,6 @@ void resetMergeResultBuf(SQuery *pQuery, SQLFunctionCtx *pCtx, SResultInfo *pRes
} }
} }
void setTableDataInfo(STableQueryInfo *pTableQueryInfo, int32_t tableIndex, int32_t groupId) {
pTableQueryInfo->groupIdx = groupId;
pTableQueryInfo->tableIndex = tableIndex;
}
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) { static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
if (pTableQueryInfo == NULL) { if (pTableQueryInfo == NULL) {
return; return;
...@@ -3132,19 +3126,6 @@ static void disableFuncInReverseScanImpl(SQInfo* pQInfo, SWindowResInfo *pWindow ...@@ -3132,19 +3126,6 @@ static void disableFuncInReverseScanImpl(SQInfo* pQInfo, SWindowResInfo *pWindow
} }
} }
} }
int32_t numOfGroups = taosArrayGetSize(pQInfo->groupInfo.pGroupList);
for(int32_t i = 0; i < numOfGroups; ++i) {
SArray *group = taosArrayGetP(pQInfo->groupInfo.pGroupList, i);
qTrace("QInfo:%p no result in group %d, continue", pQInfo, pQInfo->groupIndex - 1);
size_t t = taosArrayGetSize(group);
for (int32_t j = 0; j < t; ++j) {
SGroupItem *item = taosArrayGet(group, j);
updateTableQueryInfoForReverseScan(pQuery, item->info);
}
}
} }
void disableFuncInReverseScan(SQInfo *pQInfo) { void disableFuncInReverseScan(SQInfo *pQInfo) {
...@@ -3170,6 +3151,18 @@ void disableFuncInReverseScan(SQInfo *pQInfo) { ...@@ -3170,6 +3151,18 @@ void disableFuncInReverseScan(SQInfo *pQInfo) {
} }
} }
} }
int32_t numOfGroups = taosArrayGetSize(pQInfo->groupInfo.pGroupList);
for(int32_t i = 0; i < numOfGroups; ++i) {
SArray *group = taosArrayGetP(pQInfo->groupInfo.pGroupList, i);
size_t t = taosArrayGetSize(group);
for (int32_t j = 0; j < t; ++j) {
SGroupItem *item = taosArrayGet(group, j);
updateTableQueryInfoForReverseScan(pQuery, item->info);
}
}
} }
void switchCtxOrder(SQueryRuntimeEnv *pRuntimeEnv) { void switchCtxOrder(SQueryRuntimeEnv *pRuntimeEnv) {
...@@ -4361,6 +4354,7 @@ static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -4361,6 +4354,7 @@ static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) {
} }
} }
static int32_t xx = 0;
static int64_t queryOnDataBlocks(SQInfo *pQInfo) { static int64_t queryOnDataBlocks(SQInfo *pQInfo) {
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery; SQuery * pQuery = pRuntimeEnv->pQuery;
...@@ -4399,12 +4393,26 @@ static int64_t queryOnDataBlocks(SQInfo *pQInfo) { ...@@ -4399,12 +4393,26 @@ static int64_t queryOnDataBlocks(SQInfo *pQInfo) {
break; break;
} }
} }
if (pTableQueryInfo->id.tid == 5) {
int32_t k = 1;
printf("%d\n", k);
}
if (!QUERY_IS_ASC_QUERY(pQuery)) {
printf("-------------%d\n", xx++);
}
if (pTableQueryInfo->id.tid == 5 && !QUERY_IS_ASC_QUERY(pQuery)) {
int32_t k = 1;
printf("%d\n", k);
}
assert(pTableQueryInfo != NULL); assert(pTableQueryInfo != NULL);
restoreIntervalQueryRange(pRuntimeEnv, pTableQueryInfo); restoreIntervalQueryRange(pRuntimeEnv, pTableQueryInfo);
SDataStatis *pStatis = NULL; SDataStatis *pStatis = NULL;
SArray * pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, &blockInfo, &pStatis); SArray * pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, pQueryHandle, &blockInfo, &pStatis);
TSKEY nextKey = blockInfo.window.skey; TSKEY nextKey = blockInfo.window.skey;
if (!isIntervalQuery(pQuery)) { if (!isIntervalQuery(pQuery)) {
...@@ -6318,12 +6326,10 @@ static void buildTagQueryResult(SQInfo* pQInfo) { ...@@ -6318,12 +6326,10 @@ static void buildTagQueryResult(SQInfo* pQInfo) {
for(int32_t j = 0; j < pQuery->numOfOutput; ++j) { for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
// todo check the return value, refactor codes // todo check the return value, refactor codes
if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
tsdbGetTableName(pQInfo->tsdb, &item->id, &data); data = tsdbGetTableName(pQInfo->tsdb, &item->id, &bytes);
char* dst = pQuery->sdata[j]->data + i * (TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE); char* dst = pQuery->sdata[j]->data + i * (TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE);
STR_WITH_MAXSIZE_TO_VARSTR(dst, data, TSDB_TABLE_NAME_LEN); memcpy(dst, data, varDataTLen(data));
tfree(data);
} else {// todo refactor, return the true length of binary|nchar data } else {// todo refactor, return the true length of binary|nchar data
tsdbGetTableTagVal(pQInfo->tsdb, &item->id, pExprInfo[j].base.colInfo.colId, &type, &bytes, &data); tsdbGetTableTagVal(pQInfo->tsdb, &item->id, pExprInfo[j].base.colInfo.colId, &type, &bytes, &data);
assert(bytes == pExprInfo[j].bytes && type == pExprInfo[j].type); assert(bytes == pExprInfo[j].bytes && type == pExprInfo[j].type);
......
...@@ -81,7 +81,6 @@ typedef struct { ...@@ -81,7 +81,6 @@ typedef struct {
// ---------- TSDB TABLE DEFINITION // ---------- TSDB TABLE DEFINITION
typedef struct STable { typedef struct STable {
int8_t type; int8_t type;
char * name;
STableId tableId; STableId tableId;
int64_t superUid; // Super table UID int64_t superUid; // Super table UID
int32_t sversion; int32_t sversion;
...@@ -95,9 +94,10 @@ typedef struct STable { ...@@ -95,9 +94,10 @@ typedef struct STable {
void * streamHandler; // TODO void * streamHandler; // TODO
TSKEY lastKey; // lastkey inserted in this table, initialized as 0, TODO: make a structure TSKEY lastKey; // lastkey inserted in this table, initialized as 0, TODO: make a structure
struct STable *next; // TODO: remove the next struct STable *next; // TODO: remove the next
tstr * name; // NOTE: there a flexible string here
} STable; } STable;
#define TSDB_GET_TABLE_LAST_KEY(pTable) ((pTable)->lastKey) #define TSDB_GET_TABLE_LAST_KEY(tb) ((tb)->lastKey)
void * tsdbEncodeTable(STable *pTable, int *contLen); void * tsdbEncodeTable(STable *pTable, int *contLen);
STable *tsdbDecodeTable(void *cont, int contLen); STable *tsdbDecodeTable(void *cont, int contLen);
...@@ -120,6 +120,12 @@ typedef struct { ...@@ -120,6 +120,12 @@ typedef struct {
int maxCols; int maxCols;
} STsdbMeta; } STsdbMeta;
// element put in skiplist for each table
typedef struct STableIndexElem {
STsdbMeta* pMeta;
STable* pTable;
} STableIndexElem;
STsdbMeta *tsdbInitMeta(char *rootDir, int32_t maxTables); STsdbMeta *tsdbInitMeta(char *rootDir, int32_t maxTables);
int32_t tsdbFreeMeta(STsdbMeta *pMeta); int32_t tsdbFreeMeta(STsdbMeta *pMeta);
STSchema * tsdbGetTableSchema(STsdbMeta *pMeta, STable *pTable); STSchema * tsdbGetTableSchema(STsdbMeta *pMeta, STable *pTable);
...@@ -149,7 +155,7 @@ int32_t tsdbDropTableImpl(STsdbMeta *pMeta, STableId tableId); ...@@ -149,7 +155,7 @@ int32_t tsdbDropTableImpl(STsdbMeta *pMeta, STableId tableId);
STable *tsdbIsValidTableToInsert(STsdbMeta *pMeta, STableId tableId); STable *tsdbIsValidTableToInsert(STsdbMeta *pMeta, STableId tableId);
// int32_t tsdbInsertRowToTableImpl(SSkipListNode *pNode, STable *pTable); // int32_t tsdbInsertRowToTableImpl(SSkipListNode *pNode, STable *pTable);
STable *tsdbGetTableByUid(STsdbMeta *pMeta, int64_t uid); STable *tsdbGetTableByUid(STsdbMeta *pMeta, int64_t uid);
char * getTupleKey(const void *data); char *getTSTupleKey(const void * data);
typedef struct { typedef struct {
int blockId; int blockId;
......
...@@ -768,7 +768,7 @@ static int32_t tdInsertRowToTable(STsdbRepo *pRepo, SDataRow row, STable *pTable ...@@ -768,7 +768,7 @@ static int32_t tdInsertRowToTable(STsdbRepo *pRepo, SDataRow row, STable *pTable
if (pTable->mem == NULL) { if (pTable->mem == NULL) {
pTable->mem = (SMemTable *)calloc(1, sizeof(SMemTable)); pTable->mem = (SMemTable *)calloc(1, sizeof(SMemTable));
if (pTable->mem == NULL) return -1; if (pTable->mem == NULL) return -1;
pTable->mem->pData = tSkipListCreate(5, TSDB_DATA_TYPE_TIMESTAMP, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], 0, 0, 0, getTupleKey); pTable->mem->pData = tSkipListCreate(5, TSDB_DATA_TYPE_TIMESTAMP, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], 0, 0, 0, getTSTupleKey);
pTable->mem->keyFirst = INT64_MAX; pTable->mem->keyFirst = INT64_MAX;
pTable->mem->keyLast = 0; pTable->mem->keyLast = 0;
} }
...@@ -791,7 +791,7 @@ static int32_t tdInsertRowToTable(STsdbRepo *pRepo, SDataRow row, STable *pTable ...@@ -791,7 +791,7 @@ static int32_t tdInsertRowToTable(STsdbRepo *pRepo, SDataRow row, STable *pTable
if (pTable->mem == NULL) { if (pTable->mem == NULL) {
pTable->mem = (SMemTable *)calloc(1, sizeof(SMemTable)); pTable->mem = (SMemTable *)calloc(1, sizeof(SMemTable));
if (pTable->mem == NULL) return -1; if (pTable->mem == NULL) return -1;
pTable->mem->pData = tSkipListCreate(5, TSDB_DATA_TYPE_TIMESTAMP, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], 0, 0, 0, getTupleKey); pTable->mem->pData = tSkipListCreate(5, TSDB_DATA_TYPE_TIMESTAMP, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], 0, 0, 0, getTSTupleKey);
pTable->mem->keyFirst = INT64_MAX; pTable->mem->keyFirst = INT64_MAX;
pTable->mem->keyLast = 0; pTable->mem->keyLast = 0;
} }
......
#include <stdlib.h> #include <stdlib.h>
// #include "taosdef.h"
#include "tskiplist.h" #include "tskiplist.h"
#include "tsdb.h" #include "tsdb.h"
#include "taosdef.h" #include "taosdef.h"
...@@ -10,6 +8,8 @@ ...@@ -10,6 +8,8 @@
#define TSDB_SUPER_TABLE_SL_LEVEL 5 // TODO: may change here #define TSDB_SUPER_TABLE_SL_LEVEL 5 // TODO: may change here
#define TSDB_META_FILE_NAME "META" #define TSDB_META_FILE_NAME "META"
const int32_t DEFAULT_TAG_INDEX_COLUMN = 0;
static int tsdbFreeTable(STable *pTable); static int tsdbFreeTable(STable *pTable);
static int32_t tsdbCheckTableCfg(STableCfg *pCfg); static int32_t tsdbCheckTableCfg(STableCfg *pCfg);
static int tsdbAddTableToMeta(STsdbMeta *pMeta, STable *pTable, bool addIdx); static int tsdbAddTableToMeta(STsdbMeta *pMeta, STable *pTable, bool addIdx);
...@@ -39,11 +39,12 @@ void *tsdbEncodeTable(STable *pTable, int *contLen) { ...@@ -39,11 +39,12 @@ void *tsdbEncodeTable(STable *pTable, int *contLen) {
void *ptr = ret; void *ptr = ret;
T_APPEND_MEMBER(ptr, pTable, STable, type); T_APPEND_MEMBER(ptr, pTable, STable, type);
// Encode name // Encode name, todo refactor
*(int *)ptr = strlen(pTable->name); *(int *)ptr = varDataLen(pTable->name);
ptr = (char *)ptr + sizeof(int); ptr = (char *)ptr + sizeof(int);
memcpy(ptr, pTable->name, strlen(pTable->name)); memcpy(ptr, varDataVal(pTable->name), varDataLen(pTable->name));
ptr = (char *)ptr + strlen(pTable->name); ptr = (char *)ptr + varDataLen(pTable->name);
T_APPEND_MEMBER(ptr, &(pTable->tableId), STableId, uid); T_APPEND_MEMBER(ptr, &(pTable->tableId), STableId, uid);
T_APPEND_MEMBER(ptr, &(pTable->tableId), STableId, tid); T_APPEND_MEMBER(ptr, &(pTable->tableId), STableId, tid);
T_APPEND_MEMBER(ptr, pTable, STable, superUid); T_APPEND_MEMBER(ptr, pTable, STable, superUid);
...@@ -79,9 +80,13 @@ STable *tsdbDecodeTable(void *cont, int contLen) { ...@@ -79,9 +80,13 @@ STable *tsdbDecodeTable(void *cont, int contLen) {
T_READ_MEMBER(ptr, int8_t, pTable->type); T_READ_MEMBER(ptr, int8_t, pTable->type);
int len = *(int *)ptr; int len = *(int *)ptr;
ptr = (char *)ptr + sizeof(int); ptr = (char *)ptr + sizeof(int);
pTable->name = calloc(1, len + 1); pTable->name = calloc(1, len + VARSTR_HEADER_SIZE);
if (pTable->name == NULL) return NULL; if (pTable->name == NULL) return NULL;
memcpy(pTable->name, ptr, len);
varDataSetLen(pTable->name, len);
memcpy(pTable->name->data, ptr, len);
printf("%s\n", pTable->name->data);
ptr = (char *)ptr + len; ptr = (char *)ptr + len;
T_READ_MEMBER(ptr, int64_t, pTable->tableId.uid); T_READ_MEMBER(ptr, int64_t, pTable->tableId.uid);
T_READ_MEMBER(ptr, int32_t, pTable->tableId.tid); T_READ_MEMBER(ptr, int32_t, pTable->tableId.tid);
...@@ -105,8 +110,13 @@ void tsdbFreeEncode(void *cont) { ...@@ -105,8 +110,13 @@ void tsdbFreeEncode(void *cont) {
} }
static char* getTagIndexKey(const void* pData) { static char* getTagIndexKey(const void* pData) {
STable* table = *(STable**) pData; STableIndexElem* elem = (STableIndexElem*) pData;
return getTupleKey(table->tagVal);
SDataRow row = elem->pTable->tagVal;
STSchema* pSchema = tsdbGetTableTagSchema(elem->pMeta, elem->pTable);
STColumn* pCol = &pSchema->columns[DEFAULT_TAG_INDEX_COLUMN];
return tdGetRowDataOfCol(row, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset);
} }
int tsdbRestoreTable(void *pHandle, void *cont, int contLen) { int tsdbRestoreTable(void *pHandle, void *cont, int contLen) {
...@@ -225,36 +235,28 @@ STSchema * tsdbGetTableTagSchema(STsdbMeta *pMeta, STable *pTable) { ...@@ -225,36 +235,28 @@ STSchema * tsdbGetTableTagSchema(STsdbMeta *pMeta, STable *pTable) {
} }
} }
// todo refactor table name definition
int32_t tsdbGetTableTagVal(TsdbRepoT* repo, STableId* id, int32_t colId, int16_t* type, int16_t* bytes, char** val) { int32_t tsdbGetTableTagVal(TsdbRepoT* repo, STableId* id, int32_t colId, int16_t* type, int16_t* bytes, char** val) {
STsdbMeta* pMeta = tsdbGetMeta(repo); STsdbMeta* pMeta = tsdbGetMeta(repo);
STable* pTable = tsdbGetTableByUid(pMeta, id->uid); STable* pTable = tsdbGetTableByUid(pMeta, id->uid);
STSchema* pSchema = tsdbGetTableTagSchema(pMeta, pTable); STSchema* pSchema = tsdbGetTableTagSchema(pMeta, pTable);
STColumn* pCol = NULL; STColumn* pCol = NULL;
int32_t offset = 0;
for(int32_t col = 0; col < schemaNCols(pSchema); ++col) { for(int32_t col = 0; col < schemaNCols(pSchema); ++col) {
STColumn* p = schemaColAt(pSchema, col); STColumn* p = schemaColAt(pSchema, col);
if (p->colId == colId) { if (p->colId == colId) {
pCol = p; pCol = p;
break; break;
} }
if (p->type == TSDB_DATA_TYPE_BINARY || p->type == TSDB_DATA_TYPE_NCHAR) {
offset += sizeof(int32_t);
} else {
offset += p->bytes;
}
} }
if (pCol == NULL) { if (pCol == NULL) {
return -1; // No matched tags. Maybe the modification of tags has not been done yet. return -1; // No matched tags. Maybe the modification of tags has not been done yet.
} }
assert(pCol != NULL);
SDataRow row = (SDataRow)pTable->tagVal; SDataRow row = (SDataRow)pTable->tagVal;
char* d = tdGetRowDataOfCol(row, pCol->type, TD_DATA_ROW_HEAD_SIZE + offset); char* d = tdGetRowDataOfCol(row, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset);
*val = d; *val = d;
*type = pCol->type; *type = pCol->type;
...@@ -263,15 +265,22 @@ int32_t tsdbGetTableTagVal(TsdbRepoT* repo, STableId* id, int32_t colId, int16_t ...@@ -263,15 +265,22 @@ int32_t tsdbGetTableTagVal(TsdbRepoT* repo, STableId* id, int32_t colId, int16_t
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t tsdbGetTableName(TsdbRepoT *repo, STableId* id, char** name) { char* tsdbGetTableName(TsdbRepoT *repo, const STableId* id, int16_t* bytes) {
STsdbMeta* pMeta = tsdbGetMeta(repo); STsdbMeta* pMeta = tsdbGetMeta(repo);
STable* pTable = tsdbGetTableByUid(pMeta, id->uid); STable* pTable = tsdbGetTableByUid(pMeta, id->uid);
*name = strndup(pTable->name, TSDB_TABLE_NAME_LEN); if (pTable == NULL) {
if (*name == NULL) { if (bytes != NULL) {
return -1; *bytes = 0;
}
return NULL;
} else { } else {
return 0; if (bytes != NULL) {
*bytes = varDataLen(pTable->name);
}
return (char*) pTable->name;
} }
} }
...@@ -296,7 +305,11 @@ int32_t tsdbCreateTableImpl(STsdbMeta *pMeta, STableCfg *pCfg) { ...@@ -296,7 +305,11 @@ int32_t tsdbCreateTableImpl(STsdbMeta *pMeta, STableCfg *pCfg) {
super->schema = tdDupSchema(pCfg->schema); super->schema = tdDupSchema(pCfg->schema);
super->tagSchema = tdDupSchema(pCfg->tagSchema); super->tagSchema = tdDupSchema(pCfg->tagSchema);
super->tagVal = NULL; super->tagVal = NULL;
super->name = strdup(pCfg->sname);
// todo refactor extract method
size_t size = strnlen(pCfg->sname, TSDB_TABLE_NAME_LEN);
super->name = malloc(size + VARSTR_HEADER_SIZE);
STR_WITH_SIZE_TO_VARSTR(super->name, pCfg->sname, size);
// index the first tag column // index the first tag column
STColumn* pColSchema = schemaColAt(super->tagSchema, 0); STColumn* pColSchema = schemaColAt(super->tagSchema, 0);
...@@ -322,7 +335,11 @@ int32_t tsdbCreateTableImpl(STsdbMeta *pMeta, STableCfg *pCfg) { ...@@ -322,7 +335,11 @@ int32_t tsdbCreateTableImpl(STsdbMeta *pMeta, STableCfg *pCfg) {
} }
table->tableId = pCfg->tableId; table->tableId = pCfg->tableId;
table->name = strdup(pCfg->name);
size_t size = strnlen(pCfg->name, TSDB_TABLE_NAME_LEN);
table->name = malloc(size + VARSTR_HEADER_SIZE);
STR_WITH_SIZE_TO_VARSTR(table->name, pCfg->name, size);
table->lastKey = 0; table->lastKey = 0;
if (IS_CREATE_STABLE(pCfg)) { // TSDB_CHILD_TABLE if (IS_CREATE_STABLE(pCfg)) { // TSDB_CHILD_TABLE
table->type = TSDB_CHILD_TABLE; table->type = TSDB_CHILD_TABLE;
...@@ -483,6 +500,7 @@ static int tsdbAddTableIntoMap(STsdbMeta *pMeta, STable *pTable) { ...@@ -483,6 +500,7 @@ static int tsdbAddTableIntoMap(STsdbMeta *pMeta, STable *pTable) {
} }
return 0; return 0;
} }
static int tsdbAddTableIntoIndex(STsdbMeta *pMeta, STable *pTable) { static int tsdbAddTableIntoIndex(STsdbMeta *pMeta, STable *pTable) {
assert(pTable->type == TSDB_CHILD_TABLE && pTable != NULL); assert(pTable->type == TSDB_CHILD_TABLE && pTable != NULL);
STable* pSTable = tsdbGetTableByUid(pMeta, pTable->superUid); STable* pSTable = tsdbGetTableByUid(pMeta, pTable->superUid);
...@@ -495,11 +513,14 @@ static int tsdbAddTableIntoIndex(STsdbMeta *pMeta, STable *pTable) { ...@@ -495,11 +513,14 @@ static int tsdbAddTableIntoIndex(STsdbMeta *pMeta, STable *pTable) {
// NOTE: do not allocate the space for key, since in each skip list node, only keep the pointer to pTable, not the // NOTE: do not allocate the space for key, since in each skip list node, only keep the pointer to pTable, not the
// actual key value, and the key value will be retrieved during query through the pTable and getTagIndexKey function // actual key value, and the key value will be retrieved during query through the pTable and getTagIndexKey function
SSkipListNode* pNode = calloc(1, headSize + POINTER_BYTES); SSkipListNode* pNode = calloc(1, headSize + sizeof(STableIndexElem));
pNode->level = level; pNode->level = level;
SSkipList* list = pSTable->pIndex; SSkipList* list = pSTable->pIndex;
memcpy(SL_GET_NODE_DATA(pNode), &pTable, POINTER_BYTES); STableIndexElem* elem = (STableIndexElem*) (SL_GET_NODE_DATA(pNode));
elem->pTable = pTable;
elem->pMeta = pMeta;
tSkipListPut(list, pNode); tSkipListPut(list, pNode);
return 0; return 0;
...@@ -521,7 +542,7 @@ static int tsdbRemoveTableFromIndex(STsdbMeta *pMeta, STable *pTable) { ...@@ -521,7 +542,7 @@ static int tsdbRemoveTableFromIndex(STsdbMeta *pMeta, STable *pTable) {
static int tsdbEstimateTableEncodeSize(STable *pTable) { static int tsdbEstimateTableEncodeSize(STable *pTable) {
int size = 0; int size = 0;
size += T_MEMBER_SIZE(STable, type); size += T_MEMBER_SIZE(STable, type);
size += sizeof(int) + strlen(pTable->name); size += sizeof(int) + varDataLen(pTable->name);
size += T_MEMBER_SIZE(STable, tableId); size += T_MEMBER_SIZE(STable, tableId);
size += T_MEMBER_SIZE(STable, superUid); size += T_MEMBER_SIZE(STable, superUid);
size += T_MEMBER_SIZE(STable, sversion); size += T_MEMBER_SIZE(STable, sversion);
...@@ -538,8 +559,7 @@ static int tsdbEstimateTableEncodeSize(STable *pTable) { ...@@ -538,8 +559,7 @@ static int tsdbEstimateTableEncodeSize(STable *pTable) {
return size; return size;
} }
char *getTupleKey(const void * data) { char *getTSTupleKey(const void * data) {
SDataRow row = (SDataRow)data; SDataRow row = (SDataRow)data;
return POINTER_SHIFT(row, TD_DATA_ROW_HEAD_SIZE); return POINTER_SHIFT(row, TD_DATA_ROW_HEAD_SIZE);
} }
\ No newline at end of file
...@@ -1076,17 +1076,13 @@ static int tsdbReadRowsFromCache(SSkipListIterator* pIter, STable* pTable, TSKEY ...@@ -1076,17 +1076,13 @@ static int tsdbReadRowsFromCache(SSkipListIterator* pIter, STable* pTable, TSKEY
} }
assert(offset != -1); // todo handle error assert(offset != -1); // todo handle error
void *value = tdGetRowDataOfCol(row, pColInfo->info.type, TD_DATA_ROW_HEAD_SIZE + offset);
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
void *value = tdGetRowDataOfCol(row, pColInfo->info.type, TD_DATA_ROW_HEAD_SIZE + offset);
memcpy(pData, value, varDataTLen(value)); memcpy(pData, value, varDataTLen(value));
offset += sizeof(int32_t);
} else { } else {
memcpy(pData, dataRowTuple(row) + offset, pColInfo->info.bytes); memcpy(pData, value, pColInfo->info.bytes);
offset += pColInfo->info.bytes;
} }
} }
numOfRows++; numOfRows++;
...@@ -1225,8 +1221,8 @@ static int32_t getAllTableIdList(STable* pSuperTable, SArray* list) { ...@@ -1225,8 +1221,8 @@ static int32_t getAllTableIdList(STable* pSuperTable, SArray* list) {
while (tSkipListIterNext(iter)) { while (tSkipListIterNext(iter)) {
SSkipListNode* pNode = tSkipListIterGet(iter); SSkipListNode* pNode = tSkipListIterGet(iter);
STable* t = *(STable**)SL_GET_NODE_DATA(pNode); STableIndexElem* elem = (STableIndexElem*)(SL_GET_NODE_DATA((SSkipListNode*) pNode));
taosArrayPush(list, &t->tableId); taosArrayPush(list, &elem->pTable->tableId);
} }
tSkipListDestroyIter(iter); tSkipListDestroyIter(iter);
...@@ -1235,6 +1231,7 @@ static int32_t getAllTableIdList(STable* pSuperTable, SArray* list) { ...@@ -1235,6 +1231,7 @@ static int32_t getAllTableIdList(STable* pSuperTable, SArray* list) {
/** /**
* convert the result pointer to table id instead of table object pointer * convert the result pointer to table id instead of table object pointer
* todo remove it by using callback function to change the final result in-time.
* @param pRes * @param pRes
*/ */
static void convertQueryResult(SArray* pRes, SArray* pTableList) { static void convertQueryResult(SArray* pRes, SArray* pTableList) {
...@@ -1244,8 +1241,8 @@ static void convertQueryResult(SArray* pRes, SArray* pTableList) { ...@@ -1244,8 +1241,8 @@ static void convertQueryResult(SArray* pRes, SArray* pTableList) {
size_t size = taosArrayGetSize(pTableList); size_t size = taosArrayGetSize(pTableList);
for (int32_t i = 0; i < size; ++i) { // todo speedup by using reserve space. for (int32_t i = 0; i < size; ++i) { // todo speedup by using reserve space.
STable* pTable = taosArrayGetP(pTableList, i); STableIndexElem* elem = taosArrayGet(pTableList, i);
taosArrayPush(pRes, &pTable->tableId); taosArrayPush(pRes, &elem->pTable->tableId);
} }
} }
...@@ -1309,7 +1306,12 @@ void filterPrepare(void* expr, void* param) { ...@@ -1309,7 +1306,12 @@ void filterPrepare(void* expr, void* param) {
pInfo->q = (char*) pCond->arr; pInfo->q = (char*) pCond->arr;
} else { } else {
pInfo->q = calloc(1, pSchema->bytes); pInfo->q = calloc(1, pSchema->bytes);
tVariantDump(pCond, pInfo->q, pSchema->type); if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
varDataSetLen(pInfo->q, pCond->nLen);
tVariantDump(pCond, varDataVal(pInfo->q), pSchema->type);
} else {
tVariantDump(pCond, pInfo->q, pSchema->type);
}
} }
} }
...@@ -1341,16 +1343,16 @@ int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) { ...@@ -1341,16 +1343,16 @@ int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) {
int32_t bytes = 0; int32_t bytes = 0;
if (colIndex == TSDB_TBNAME_COLUMN_INDEX) { if (colIndex == TSDB_TBNAME_COLUMN_INDEX) {
f1 = pTable1->name; f1 = (char*) pTable1->name;
f2 = pTable2->name; f2 = (char*) pTable2->name;
type = TSDB_DATA_TYPE_BINARY; type = TSDB_DATA_TYPE_BINARY;
bytes = TSDB_TABLE_NAME_LEN; bytes = TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE;
} else { } else {
f1 = dataRowTuple(pTable1->tagVal); STColumn* pCol = schemaColAt(pTableGroupSupp->pTagSchema, colIndex);
f2 = dataRowTuple(pTable2->tagVal); bytes = pCol->bytes;
type = schemaColAt(pTableGroupSupp->pTagSchema, colIndex)->type; f1 = tdGetRowDataOfCol(pTable1->tagVal, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset);
bytes = schemaColAt(pTableGroupSupp->pTagSchema, colIndex)->bytes; f2 = tdGetRowDataOfCol(pTable2->tagVal, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset);
} }
int32_t ret = doCompare(f1, f2, type, bytes); int32_t ret = doCompare(f1, f2, type, bytes);
...@@ -1428,24 +1430,20 @@ SArray* createTableGroup(SArray* pTableList, STSchema* pTagSchema, SColIndex* pC ...@@ -1428,24 +1430,20 @@ SArray* createTableGroup(SArray* pTableList, STSchema* pTagSchema, SColIndex* pC
bool tSkipListNodeFilterCallback(const void* pNode, void* param) { bool tSkipListNodeFilterCallback(const void* pNode, void* param) {
tQueryInfo* pInfo = (tQueryInfo*) param; tQueryInfo* pInfo = (tQueryInfo*) param;
STable* pTable = *(STable**)(SL_GET_NODE_DATA((SSkipListNode*)pNode)); STableIndexElem* elem = (STableIndexElem*)(SL_GET_NODE_DATA((SSkipListNode*)pNode));
char* val = NULL; char* val = NULL;
int8_t type = pInfo->sch.type; int8_t type = pInfo->sch.type;
if (pInfo->colIndex == TSDB_TBNAME_COLUMN_INDEX) { if (pInfo->colIndex == TSDB_TBNAME_COLUMN_INDEX) {
val = pTable->name; val = (char*) elem->pTable->name;
type = TSDB_DATA_TYPE_BINARY; type = TSDB_DATA_TYPE_BINARY;
} else { } else {
STSchema* pTSchema = (STSchema*) pInfo->param; // todo table schema is identical to stable schema?? STSchema* pTSchema = (STSchema*) pInfo->param; // todo table schema is identical to stable schema??
int32_t offset = pTSchema->columns[pInfo->colIndex].offset; int32_t offset = pTSchema->columns[pInfo->colIndex].offset;
if (pInfo->sch.type == TSDB_DATA_TYPE_BINARY || pInfo->sch.type == TSDB_DATA_TYPE_NCHAR) { val = tdGetRowDataOfCol(elem->pTable->tagVal, pInfo->sch.type, TD_DATA_ROW_HEAD_SIZE + offset);
val = tdGetRowDataOfCol(pTable->tagVal, pInfo->sch.type, TD_DATA_ROW_HEAD_SIZE + offset);
} else {
val = dataRowTuple(pTable->tagVal) + offset;
}
} }
int32_t ret = 0; int32_t ret = 0;
...@@ -1456,8 +1454,6 @@ bool tSkipListNodeFilterCallback(const void* pNode, void* param) { ...@@ -1456,8 +1454,6 @@ bool tSkipListNodeFilterCallback(const void* pNode, void* param) {
ret = pInfo->compare(val, pInfo->q); ret = pInfo->compare(val, pInfo->q);
} }
} else { } else {
// tVariant t = {0};
// tVariantCreateFromBinary(&t, val, (uint32_t)pInfo->sch.bytes, type);
ret = pInfo->compare(val, pInfo->q); ret = pInfo->compare(val, pInfo->q);
} }
...@@ -1502,7 +1498,7 @@ static int32_t doQueryTableList(STable* pSTable, SArray* pRes, tExprNode* pExpr) ...@@ -1502,7 +1498,7 @@ static int32_t doQueryTableList(STable* pSTable, SArray* pRes, tExprNode* pExpr)
.pExtInfo = pSTable->tagSchema, .pExtInfo = pSTable->tagSchema,
}; };
SArray* pTableList = taosArrayInit(8, POINTER_BYTES); SArray* pTableList = taosArrayInit(8, sizeof(STableIndexElem));
tExprTreeTraverse(pExpr, pSTable->pIndex, pTableList, &supp); tExprTreeTraverse(pExpr, pSTable->pIndex, pTableList, &supp);
tExprTreeDestroy(&pExpr, destroyHelper); tExprTreeDestroy(&pExpr, destroyHelper);
......
...@@ -144,11 +144,11 @@ static void tqsortImpl(void *src, int32_t start, int32_t end, size_t size, const ...@@ -144,11 +144,11 @@ static void tqsortImpl(void *src, int32_t start, int32_t end, size_t size, const
} }
if (leftPartEnd > start) { if (leftPartEnd > start) {
tqsortImpl(src, size, start, leftPartEnd, param, comparFn, buf); tqsortImpl(src, start, leftPartEnd, size, param, comparFn, buf);
} }
if (rightPartStart < end) { if (rightPartStart < end) {
tqsortImpl(src, size, rightPartStart, end, param, comparFn, buf); tqsortImpl(src, rightPartStart, end, size, param, comparFn, buf);
} }
} }
......
...@@ -60,8 +60,15 @@ int32_t compareDoubleVal(const void *pLeft, const void *pRight) { ...@@ -60,8 +60,15 @@ int32_t compareDoubleVal(const void *pLeft, const void *pRight) {
} }
} }
int32_t compareStrVal(const void *pLeft, const void *pRight) { int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight) {
return (int32_t)strcmp(pLeft, pRight); int32_t len1 = varDataLen(pLeft);
int32_t len2 = varDataLen(pRight);
if (len1 != len2) {
return len1 > len2? 1:-1;
} else {
return (int32_t) strncmp(varDataVal(pLeft), varDataVal(pRight), len1);
}
} }
int32_t compareWStrVal(const void *pLeft, const void *pRight) { int32_t compareWStrVal(const void *pLeft, const void *pRight) {
...@@ -267,7 +274,7 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) { ...@@ -267,7 +274,7 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) {
} else if (optr == TSDB_RELATION_IN) { } else if (optr == TSDB_RELATION_IN) {
comparFn = compareFindStrInArray; comparFn = compareFindStrInArray;
} else { /* normal relational comparFn */ } else { /* normal relational comparFn */
comparFn = compareStrVal; comparFn = compareLenPrefixedStr;
} }
break; break;
...@@ -296,6 +303,7 @@ __compar_fn_t getKeyComparFunc(int32_t keyType) { ...@@ -296,6 +303,7 @@ __compar_fn_t getKeyComparFunc(int32_t keyType) {
switch (keyType) { switch (keyType) {
case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_BOOL:
comparFn = compareInt8Val; comparFn = compareInt8Val;
break; break;
case TSDB_DATA_TYPE_SMALLINT: case TSDB_DATA_TYPE_SMALLINT:
...@@ -308,17 +316,13 @@ __compar_fn_t getKeyComparFunc(int32_t keyType) { ...@@ -308,17 +316,13 @@ __compar_fn_t getKeyComparFunc(int32_t keyType) {
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP:
comparFn = compareInt64Val; comparFn = compareInt64Val;
break; break;
case TSDB_DATA_TYPE_BOOL:
comparFn = compareInt32Val;
break;
case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE: case TSDB_DATA_TYPE_DOUBLE:
comparFn = compareDoubleVal; comparFn = compareDoubleVal;
break; break;
case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_BINARY:
comparFn = compareStrVal; comparFn = compareLenPrefixedStr;
break; break;
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR:
...@@ -349,13 +353,20 @@ int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) { ...@@ -349,13 +353,20 @@ int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) {
} }
return (ret < 0) ? -1 : 1; return (ret < 0) ? -1 : 1;
} }
default: { default: { // todo refactor
int32_t ret = strncmp(f1, f2, (size_t)size); tstr* t1 = (tstr*) f1;
if (ret == 0) { tstr* t2 = (tstr*) f2;
return ret;
}
return (ret < 0) ? -1 : 1; if (t1->len != t2->len) {
return t1->len > t2->len? 1:-1;
} else {
int32_t ret = strncmp(t1->data, t2->data, t1->len);
if (ret == 0) {
return 0;
} else {
return ret < 0? -1:1;
}
}
} }
} }
} }
...@@ -27,11 +27,15 @@ sql create table $tb using $mt tags( "1" ) ...@@ -27,11 +27,15 @@ sql create table $tb using $mt tags( "1" )
sql insert into $tb values (now, 1) sql insert into $tb values (now, 1)
sql select * from $tb sql select * from $tb
print ===>rows $rows, data $data01 #print ===>rows $rows, data $data01
if $rows != 1 then if $rows != 1 then
print expect 1, actual: $rows
return -1 return -1
endi endi
if $data01 != 1 then if $data01 != 1 then
print expect 1 actual: $data01
return -1 return -1
endi endi
...@@ -66,8 +70,10 @@ sql select * from $tb ...@@ -66,8 +70,10 @@ sql select * from $tb
print ===>rows $rows, data $data01 print ===>rows $rows, data $data01
if $rows != 1 then if $rows != 1 then
return -1 return -1
endi endi
if $data01 != 1 then if $data01 != 1 then
print expect 1, actual $data01
return -1 return -1
endi endi
...@@ -80,6 +86,7 @@ if $data01 != 1 then ...@@ -80,6 +86,7 @@ if $data01 != 1 then
return -1 return -1
endi endi
if $data02 != 3 then if $data02 != 3 then
print expect 3 actual: $data02
return -1 return -1
endi endi
......
...@@ -132,7 +132,9 @@ endi ...@@ -132,7 +132,9 @@ endi
print =============== step6 print =============== step6
sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = 1 group by tgcol sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = 1 group by tgcol
print $data00 $data01 $data02 $data03 $data04 $data05 $data06 print $data00 $data01 $data02 $data03 $data04 $data05 $data06
if $data00 != 100 then print $data10 $data11 $data12 $data13 $data14 $data15 $data16
if $data00 != 100 then
print expect 100, actual $data00
return -1 return -1
endi endi
......
...@@ -14,6 +14,7 @@ sleep 2000 ...@@ -14,6 +14,7 @@ sleep 2000
run general/parser/columnValue.sim run general/parser/columnValue.sim
sleep 2000 sleep 2000
run general/parser/commit.sim run general/parser/commit.sim
sleep 2000
run general/parser/create_db.sim run general/parser/create_db.sim
sleep 2000 sleep 2000
run general/parser/create_mt.sim run general/parser/create_mt.sim
...@@ -22,21 +23,21 @@ run general/parser/create_tb.sim ...@@ -22,21 +23,21 @@ run general/parser/create_tb.sim
sleep 2000 sleep 2000
run general/parser/dbtbnameValidate.sim run general/parser/dbtbnameValidate.sim
sleep 2000 sleep 2000
run general/parser/fill.sim
sleep 2000
run general/parser/fill_stb.sim
sleep 2000
run general/parser/first_last.sim
sleep 2000
run general/parser/import_commit1.sim run general/parser/import_commit1.sim
sleep 2000 sleep 2000
run general/parser/import_commit2.sim run general/parser/import_commit2.sim
sleep 2000 sleep 2000
run general/parser/import_commit3.sim run general/parser/import_commit3.sim
sleep 2000 sleep 2000
run general/parser/insert_tb.sim
sleep 2000
run general/parser/first_last.sim
sleep 2000
run general/parser/import_file.sim run general/parser/import_file.sim
sleep 2000 sleep 2000
run general/parser/insert_tb.sim run general/parser/fill.sim
sleep 2000
run general/parser/fill_stb.sim
sleep 2000 sleep 2000
run general/parser/tags_dynamically_specifiy.sim run general/parser/tags_dynamically_specifiy.sim
sleep 2000 sleep 2000
......
...@@ -122,7 +122,8 @@ if $rows != 100 then ...@@ -122,7 +122,8 @@ if $rows != 100 then
return -1 return -1
endi endi
sql select * from $mt where tgcol = 1 sql select * from $mt where tgcol = 1
if $rows != 100 then if $rows != 100 then
print expect 100, actual:$rows
return -1 return -1
endi endi
sql select * from $mt where tgcol <> 1 sql select * from $mt where tgcol <> 1
......
...@@ -122,7 +122,8 @@ endi ...@@ -122,7 +122,8 @@ endi
print =============== step14 print =============== step14
sql select count(tbcol) as c from $mt where ts > 1000 group by tgcol sql select count(tbcol) as c from $mt where ts > 1000 group by tgcol
print $data00 $data01 $data02 $data03 $data04 $data05 $data06 print $data00 $data01 $data02 $data03 $data04 $data05 $data06
if $data00 != 100 then if $data00 != 100 then
print expect 100, actual $data00
return -1 return -1
endi endi
......
...@@ -99,7 +99,8 @@ echo "cDebugFlag 135" >> $TAOS_CFG ...@@ -99,7 +99,8 @@ echo "cDebugFlag 135" >> $TAOS_CFG
echo "httpDebugFlag 135" >> $TAOS_CFG echo "httpDebugFlag 135" >> $TAOS_CFG
echo "monitorDebugFlag 135" >> $TAOS_CFG echo "monitorDebugFlag 135" >> $TAOS_CFG
echo "udebugFlag 135" >> $TAOS_CFG echo "udebugFlag 135" >> $TAOS_CFG
echo "clog 0" >> $TAOS_CFG echo "tablemetakeeptimer 5" >> $TAOS_CFG
echo "wal 0" >> $TAOS_CFG
echo "asyncLog 0" >> $TAOS_CFG echo "asyncLog 0" >> $TAOS_CFG
echo "locale en_US.UTF-8" >> $TAOS_CFG echo "locale en_US.UTF-8" >> $TAOS_CFG
echo " " >> $TAOS_CFG echo " " >> $TAOS_CFG
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册