提交 e17396be 编写于 作者: X Xiaoyu Wang

fix: some problems of parser

上级 a395b3e9
...@@ -121,7 +121,7 @@ typedef enum EFunctionType { ...@@ -121,7 +121,7 @@ typedef enum EFunctionType {
// internal function // internal function
FUNCTION_TYPE_SELECT_VALUE, FUNCTION_TYPE_SELECT_VALUE,
FUNCTION_TYPE_BLOCK_DIST, // block distribution aggregate function FUNCTION_TYPE_BLOCK_DIST, // block distribution aggregate function
// distributed splitting functions // distributed splitting functions
FUNCTION_TYPE_APERCENTILE_PARTIAL, FUNCTION_TYPE_APERCENTILE_PARTIAL,
...@@ -170,6 +170,7 @@ bool fmIsMultiResFunc(int32_t funcId); ...@@ -170,6 +170,7 @@ bool fmIsMultiResFunc(int32_t funcId);
bool fmIsRepeatScanFunc(int32_t funcId); bool fmIsRepeatScanFunc(int32_t funcId);
bool fmIsUserDefinedFunc(int32_t funcId); bool fmIsUserDefinedFunc(int32_t funcId);
bool fmIsDistExecFunc(int32_t funcId); bool fmIsDistExecFunc(int32_t funcId);
bool fmIsForbidFillFunc(int32_t funcId);
int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc); int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc);
......
...@@ -47,7 +47,7 @@ typedef struct SDatabaseOptions { ...@@ -47,7 +47,7 @@ typedef struct SDatabaseOptions {
int32_t maxRowsPerBlock; int32_t maxRowsPerBlock;
int32_t minRowsPerBlock; int32_t minRowsPerBlock;
SNodeList* pKeep; SNodeList* pKeep;
int32_t keep[3]; int64_t keep[3];
int32_t pages; int32_t pages;
int32_t pagesize; int32_t pagesize;
char precisionStr[3]; char precisionStr[3];
......
...@@ -655,6 +655,7 @@ int32_t* taosGetErrno(); ...@@ -655,6 +655,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2654) #define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2654)
#define TSDB_CODE_PAR_INVALID_DELETE_WHERE TAOS_DEF_ERROR_CODE(0, 0x2655) #define TSDB_CODE_PAR_INVALID_DELETE_WHERE TAOS_DEF_ERROR_CODE(0, 0x2655)
#define TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG TAOS_DEF_ERROR_CODE(0, 0x2656) #define TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG TAOS_DEF_ERROR_CODE(0, 0x2656)
#define TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x2657)
//planner //planner
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700) #define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
......
...@@ -1424,10 +1424,10 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in ...@@ -1424,10 +1424,10 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
char tmp[128] = {0}; char tmp[128] = {0};
int32_t len = 0; int32_t len = 0;
if (pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep1 || pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep2) { if (pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep1 || pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep2) {
len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%d,%d,%d", pDb->cfg.daysToKeep1, pDb->cfg.daysToKeep2, len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%dm,%dm,%dm", pDb->cfg.daysToKeep1, pDb->cfg.daysToKeep2,
pDb->cfg.daysToKeep0); pDb->cfg.daysToKeep0);
} else { } else {
len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%d,%d,%d", pDb->cfg.daysToKeep0, pDb->cfg.daysToKeep1, len = sprintf(&tmp[VARSTR_HEADER_SIZE], "%dm,%dm,%dm", pDb->cfg.daysToKeep0, pDb->cfg.daysToKeep1,
pDb->cfg.daysToKeep2); pDb->cfg.daysToKeep2);
} }
...@@ -1592,4 +1592,3 @@ static void mndCancelGetNextDb(SMnode *pMnode, void *pIter) { ...@@ -1592,4 +1592,3 @@ static void mndCancelGetNextDb(SMnode *pMnode, void *pIter) {
SSdb *pSdb = pMnode->pSdb; SSdb *pSdb = pMnode->pSdb;
sdbCancelFetch(pSdb, pIter); sdbCancelFetch(pSdb, pIter);
} }
...@@ -41,6 +41,7 @@ extern "C" { ...@@ -41,6 +41,7 @@ extern "C" {
#define FUNC_MGT_SCAN_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(12) #define FUNC_MGT_SCAN_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(12)
#define FUNC_MGT_SELECT_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(13) #define FUNC_MGT_SELECT_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(13)
#define FUNC_MGT_REPEAT_SCAN_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(14) #define FUNC_MGT_REPEAT_SCAN_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(14)
#define FUNC_MGT_FORBID_FILL_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(15)
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0) #define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
......
...@@ -294,7 +294,8 @@ static int32_t translateApercentileImpl(SFunctionNode* pFunc, char* pErrBuf, int ...@@ -294,7 +294,8 @@ static int32_t translateApercentileImpl(SFunctionNode* pFunc, char* pErrBuf, int
pValue->notReserved = true; pValue->notReserved = true;
} }
pFunc->node.resType = (SDataType){.bytes = getApercentileMaxSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY}; pFunc->node.resType =
(SDataType){.bytes = getApercentileMaxSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
} else { } else {
if (1 != numOfParams) { if (1 != numOfParams) {
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
...@@ -479,7 +480,8 @@ static int32_t translateElapsedImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t ...@@ -479,7 +480,8 @@ static int32_t translateElapsedImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t
} }
} }
pFunc->node.resType = (SDataType){.bytes = getElapsedInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY}; pFunc->node.resType =
(SDataType){.bytes = getElapsedInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
} else { } else {
if (1 != numOfParams) { if (1 != numOfParams) {
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
...@@ -593,7 +595,8 @@ static int32_t translateHistogramImpl(SFunctionNode* pFunc, char* pErrBuf, int32 ...@@ -593,7 +595,8 @@ static int32_t translateHistogramImpl(SFunctionNode* pFunc, char* pErrBuf, int32
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
} }
pFunc->node.resType = (SDataType){.bytes = getHistogramInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY}; pFunc->node.resType =
(SDataType){.bytes = getHistogramInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
} else { } else {
if (1 != numOfParams) { if (1 != numOfParams) {
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
...@@ -631,7 +634,8 @@ static int32_t translateHLLImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len ...@@ -631,7 +634,8 @@ static int32_t translateHLLImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len
} }
if (isPartial) { if (isPartial) {
pFunc->node.resType = (SDataType){.bytes = getHistogramInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY}; pFunc->node.resType =
(SDataType){.bytes = getHistogramInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
} else { } else {
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT}; pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
} }
...@@ -1127,7 +1131,7 @@ static bool validateTimezoneFormat(const SValueNode* pVal) { ...@@ -1127,7 +1131,7 @@ static bool validateTimezoneFormat(const SValueNode* pVal) {
char* tz = varDataVal(pVal->datum.p); char* tz = varDataVal(pVal->datum.p);
int32_t len = varDataLen(pVal->datum.p); int32_t len = varDataLen(pVal->datum.p);
char buf[3] = {0}; char buf[3] = {0};
int8_t hour = -1, minute = -1; int8_t hour = -1, minute = -1;
if (len == 0) { if (len == 0) {
return false; return false;
...@@ -1320,7 +1324,7 @@ static int32_t translateSelectValue(SFunctionNode* pFunc, char* pErrBuf, int32_t ...@@ -1320,7 +1324,7 @@ static int32_t translateSelectValue(SFunctionNode* pFunc, char* pErrBuf, int32_t
} }
static int32_t translateBlockDistFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { static int32_t translateBlockDistFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
pFunc->node.resType = (SDataType) {.bytes = 128, .type = TSDB_DATA_TYPE_VARCHAR}; pFunc->node.resType = (SDataType){.bytes = 128, .type = TSDB_DATA_TYPE_VARCHAR};
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
...@@ -1329,7 +1333,6 @@ static bool getBlockDistFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv ...@@ -1329,7 +1333,6 @@ static bool getBlockDistFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv
return true; return true;
} }
// clang-format off // clang-format off
const SBuiltinFuncDefinition funcMgtBuiltins[] = { const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{ {
...@@ -1608,7 +1611,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { ...@@ -1608,7 +1611,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{ {
.name = "histogram", .name = "histogram",
.type = FUNCTION_TYPE_HISTOGRAM, .type = FUNCTION_TYPE_HISTOGRAM,
.classification = FUNC_MGT_AGG_FUNC, .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_FORBID_FILL_FUNC,
.translateFunc = translateHistogram, .translateFunc = translateHistogram,
.getEnvFunc = getHistogramFuncEnv, .getEnvFunc = getHistogramFuncEnv,
.initFunc = histogramFunctionSetup, .initFunc = histogramFunctionSetup,
......
...@@ -159,6 +159,8 @@ bool fmIsRepeatScanFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, ...@@ -159,6 +159,8 @@ bool fmIsRepeatScanFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId,
bool fmIsUserDefinedFunc(int32_t funcId) { return funcId > FUNC_UDF_ID_START; } bool fmIsUserDefinedFunc(int32_t funcId) { return funcId > FUNC_UDF_ID_START; }
bool fmIsForbidFillFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORBID_FILL_FUNC); }
void fmFuncMgtDestroy() { void fmFuncMgtDestroy() {
void* m = gFunMgtService.pFuncNameHashTable; void* m = gFunMgtService.pFuncNameHashTable;
if (m != NULL && atomic_val_compare_exchange_ptr((void**)&gFunMgtService.pFuncNameHashTable, m, 0) == m) { if (m != NULL && atomic_val_compare_exchange_ptr((void**)&gFunMgtService.pFuncNameHashTable, m, 0) == m) {
......
...@@ -346,25 +346,30 @@ SNode* createPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLitera ...@@ -346,25 +346,30 @@ SNode* createPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLitera
return (SNode*)val; return (SNode*)val;
} }
static int32_t addParamToLogicConditionNode(SLogicConditionNode* pCond, SNode* pParam) {
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam) && pCond->condType == ((SLogicConditionNode*)pParam)->condType) {
int32_t code = nodesListAppendList(pCond->pParameterList, ((SLogicConditionNode*)pParam)->pParameterList);
((SLogicConditionNode*)pParam)->pParameterList = NULL;
nodesDestroyNode(pParam);
return code;
} else {
return nodesListAppend(pCond->pParameterList, pParam);
}
}
SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2) { SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2) {
CHECK_PARSER_STATUS(pCxt); CHECK_PARSER_STATUS(pCxt);
SLogicConditionNode* cond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); SLogicConditionNode* cond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION);
CHECK_OUT_OF_MEM(cond); CHECK_OUT_OF_MEM(cond);
cond->condType = type; cond->condType = type;
cond->pParameterList = nodesMakeList(); cond->pParameterList = nodesMakeList();
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam1) && type == ((SLogicConditionNode*)pParam1)->condType) { int32_t code = addParamToLogicConditionNode(cond, pParam1);
nodesListAppendList(cond->pParameterList, ((SLogicConditionNode*)pParam1)->pParameterList); if (TSDB_CODE_SUCCESS == code && NULL != pParam2) {
((SLogicConditionNode*)pParam1)->pParameterList = NULL; code = addParamToLogicConditionNode(cond, pParam2);
nodesDestroyNode(pParam1);
} else {
nodesListAppend(cond->pParameterList, pParam1);
} }
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam2) && type == ((SLogicConditionNode*)pParam2)->condType) { if (TSDB_CODE_SUCCESS != code) {
nodesListAppendList(cond->pParameterList, ((SLogicConditionNode*)pParam2)->pParameterList); nodesDestroyNode(cond);
((SLogicConditionNode*)pParam2)->pParameterList = NULL; return NULL;
nodesDestroyNode(pParam2);
} else {
nodesListAppend(cond->pParameterList, pParam2);
} }
return (SNode*)cond; return (SNode*)cond;
} }
......
...@@ -733,7 +733,7 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD ...@@ -733,7 +733,7 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD
} }
int32_t len = 0; int32_t len = 0;
if (!taosMbsToUcs4(pVal->literal, pVal->node.resType.bytes, (TdUcs4*)varDataVal(pVal->datum.p), if (!taosMbsToUcs4(pVal->literal, strlen(pVal->literal), (TdUcs4*)varDataVal(pVal->datum.p),
targetDt.bytes - VARSTR_HEADER_SIZE, &len)) { targetDt.bytes - VARSTR_HEADER_SIZE, &len)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal); return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
} }
...@@ -974,6 +974,9 @@ static int32_t getFuncInfo(STranslateContext* pCxt, SFunctionNode* pFunc) { ...@@ -974,6 +974,9 @@ static int32_t getFuncInfo(STranslateContext* pCxt, SFunctionNode* pFunc) {
} }
static int32_t translateAggFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { static int32_t translateAggFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (!fmIsAggFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
if (beforeHaving(pCxt->currClause)) { if (beforeHaving(pCxt->currClause)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
} }
...@@ -991,6 +994,9 @@ static int32_t translateAggFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { ...@@ -991,6 +994,9 @@ static int32_t translateAggFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
} }
static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (!fmIsScanPseudoColumnFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
if (0 == LIST_LENGTH(pFunc->pParameterList)) { if (0 == LIST_LENGTH(pFunc->pParameterList)) {
if (QUERY_NODE_REAL_TABLE != nodeType(pCxt->pCurrSelectStmt->pFromTable)) { if (QUERY_NODE_REAL_TABLE != nodeType(pCxt->pCurrSelectStmt->pFromTable)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TBNAME); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TBNAME);
...@@ -1007,6 +1013,9 @@ static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SFunctionN ...@@ -1007,6 +1013,9 @@ static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SFunctionN
} }
static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (!fmIsIndefiniteRowsFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
if (SQL_CLAUSE_SELECT != pCxt->currClause || pCxt->pCurrSelectStmt->hasIndefiniteRowsFunc || if (SQL_CLAUSE_SELECT != pCxt->currClause || pCxt->pCurrSelectStmt->hasIndefiniteRowsFunc ||
pCxt->pCurrSelectStmt->hasAggFuncs) { pCxt->pCurrSelectStmt->hasAggFuncs) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
...@@ -1017,6 +1026,18 @@ static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNod ...@@ -1017,6 +1026,18 @@ static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNod
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t translateForbidFillFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (!fmIsForbidFillFunc(pFunc->funcId)) {
return TSDB_CODE_SUCCESS;
}
if (NULL != pCxt->pCurrSelectStmt->pWindow &&
QUERY_NODE_INTERVAL_WINDOW == nodeType(pCxt->pCurrSelectStmt->pWindow) &&
NULL != ((SIntervalWindowNode*)pCxt->pCurrSelectStmt->pWindow)->pFill) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC, pFunc->functionName);
}
return TSDB_CODE_SUCCESS;
}
static void setFuncClassification(SSelectStmt* pSelect, SFunctionNode* pFunc) { static void setFuncClassification(SSelectStmt* pSelect, SFunctionNode* pFunc) {
if (NULL != pSelect) { if (NULL != pSelect) {
pSelect->hasAggFuncs = pSelect->hasAggFuncs ? true : fmIsAggFunc(pFunc->funcId); pSelect->hasAggFuncs = pSelect->hasAggFuncs ? true : fmIsAggFunc(pFunc->funcId);
...@@ -1034,15 +1055,18 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) ...@@ -1034,15 +1055,18 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
} }
pCxt->errCode = getFuncInfo(pCxt, pFunc); pCxt->errCode = getFuncInfo(pCxt, pFunc);
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsAggFunc(pFunc->funcId)) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
pCxt->errCode = translateAggFunc(pCxt, pFunc); pCxt->errCode = translateAggFunc(pCxt, pFunc);
} }
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsScanPseudoColumnFunc(pFunc->funcId)) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
pCxt->errCode = translateScanPseudoColumnFunc(pCxt, pFunc); pCxt->errCode = translateScanPseudoColumnFunc(pCxt, pFunc);
} }
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsIndefiniteRowsFunc(pFunc->funcId)) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
pCxt->errCode = translateIndefiniteRowsFunc(pCxt, pFunc); pCxt->errCode = translateIndefiniteRowsFunc(pCxt, pFunc);
} }
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
pCxt->errCode = translateForbidFillFunc(pCxt, pFunc);
}
if (TSDB_CODE_SUCCESS == pCxt->errCode) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
setFuncClassification(pCxt->pCurrSelectStmt, pFunc); setFuncClassification(pCxt->pCurrSelectStmt, pFunc);
} }
...@@ -2365,7 +2389,9 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete ...@@ -2365,7 +2389,9 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
} }
SNode* pRetention = NULL; SValueNode* pPrevFreq = NULL;
SValueNode* pPrevKeep = NULL;
SNode* pRetention = NULL;
FOREACH(pRetention, pRetentions) { FOREACH(pRetention, pRetentions) {
SNode* pNode = NULL; SNode* pNode = NULL;
FOREACH(pNode, ((SNodeListNode*)pRetention)->pNodeList) { FOREACH(pNode, ((SNodeListNode*)pRetention)->pNodeList) {
...@@ -2374,6 +2400,16 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete ...@@ -2374,6 +2400,16 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete
return pCxt->errCode; return pCxt->errCode;
} }
} }
SValueNode* pFreq = (SValueNode*)nodesListGetNode(((SNodeListNode*)pRetention)->pNodeList, 0);
SValueNode* pKeep = (SValueNode*)nodesListGetNode(((SNodeListNode*)pRetention)->pNodeList, 1);
if (pFreq->datum.i <= 0 || 'n' == pFreq->unit || 'y' == pFreq->unit || pFreq->datum.i >= pKeep->datum.i ||
(NULL != pPrevFreq && pPrevFreq->datum.i >= pFreq->datum.i) ||
(NULL != pPrevKeep && pPrevKeep->datum.i > pKeep->datum.i)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
}
pPrevFreq = pFreq;
pPrevKeep = pKeep;
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
...@@ -2593,12 +2629,23 @@ static int32_t checkTableSmaOption(STranslateContext* pCxt, SCreateTableStmt* pS ...@@ -2593,12 +2629,23 @@ static int32_t checkTableSmaOption(STranslateContext* pCxt, SCreateTableStmt* pS
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static bool validRollupFunc(const char* pFunc) {
static const char* rollupFuncs[] = {"avg", "sum", "min", "max", "last", "first"};
static const int32_t numOfRollupFuncs = (sizeof(rollupFuncs) / sizeof(char*));
for (int i = 0; i < numOfRollupFuncs; ++i) {
if (0 == strcmp(rollupFuncs[i], pFunc)) {
return true;
}
}
return false;
}
static int32_t checkTableRollupOption(STranslateContext* pCxt, SNodeList* pFuncs) { static int32_t checkTableRollupOption(STranslateContext* pCxt, SNodeList* pFuncs) {
if (NULL == pFuncs) { if (NULL == pFuncs) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
if (1 != LIST_LENGTH(pFuncs)) { if (1 != LIST_LENGTH(pFuncs) || !validRollupFunc(((SFunctionNode*)nodesListGetNode(pFuncs, 0))->functionName)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROLLUP_OPTION); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROLLUP_OPTION);
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
...@@ -3083,15 +3130,14 @@ static int32_t translateAlterTable(STranslateContext* pCxt, SAlterTableStmt* pSt ...@@ -3083,15 +3130,14 @@ static int32_t translateAlterTable(STranslateContext* pCxt, SAlterTableStmt* pSt
SName tableName; SName tableName;
tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), alterReq.name); tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), alterReq.name);
alterReq.alterType = pStmt->alterType; alterReq.alterType = pStmt->alterType;
if (TSDB_ALTER_TABLE_UPDATE_TAG_VAL == pStmt->alterType) { if (TSDB_ALTER_TABLE_UPDATE_TAG_VAL == pStmt->alterType || TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME == pStmt->alterType) {
return TSDB_CODE_FAILED; return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
} else {
if (TSDB_CODE_SUCCESS != setAlterTableField(pStmt, &alterReq)) {
return TSDB_CODE_OUT_OF_MEMORY;
}
} }
int32_t code = setAlterTableField(pStmt, &alterReq);
return buildCmdMsg(pCxt, TDMT_MND_ALTER_STB, (FSerializeFunc)tSerializeSMAlterStbReq, &alterReq); if (TSDB_CODE_SUCCESS == code) {
code = buildCmdMsg(pCxt, TDMT_MND_ALTER_STB, (FSerializeFunc)tSerializeSMAlterStbReq, &alterReq);
}
return code;
} }
static int32_t translateUseDatabase(STranslateContext* pCxt, SUseDatabaseStmt* pStmt) { static int32_t translateUseDatabase(STranslateContext* pCxt, SUseDatabaseStmt* pStmt) {
...@@ -3171,7 +3217,7 @@ static int32_t nodeTypeToShowType(ENodeType nt) { ...@@ -3171,7 +3217,7 @@ static int32_t nodeTypeToShowType(ENodeType nt) {
case QUERY_NODE_SHOW_QUERIES_STMT: case QUERY_NODE_SHOW_QUERIES_STMT:
return TSDB_MGMT_TABLE_QUERIES; return TSDB_MGMT_TABLE_QUERIES;
case QUERY_NODE_SHOW_VARIABLE_STMT: case QUERY_NODE_SHOW_VARIABLE_STMT:
return 0; // todo return TSDB_MGMT_TABLE_CONFIGS;
default: default:
break; break;
} }
...@@ -3778,6 +3824,7 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { ...@@ -3778,6 +3824,7 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
case QUERY_NODE_SHOW_CONNECTIONS_STMT: case QUERY_NODE_SHOW_CONNECTIONS_STMT:
case QUERY_NODE_SHOW_QUERIES_STMT: case QUERY_NODE_SHOW_QUERIES_STMT:
case QUERY_NODE_SHOW_TOPICS_STMT: case QUERY_NODE_SHOW_TOPICS_STMT:
case QUERY_NODE_SHOW_VARIABLE_STMT:
code = translateShow(pCxt, (SShowStmt*)pNode); code = translateShow(pCxt, (SShowStmt*)pNode);
break; break;
case QUERY_NODE_CREATE_INDEX_STMT: case QUERY_NODE_CREATE_INDEX_STMT:
...@@ -4932,7 +4979,11 @@ static int32_t buildAlterTbReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, ...@@ -4932,7 +4979,11 @@ static int32_t buildAlterTbReq(STranslateContext* pCxt, SAlterTableStmt* pStmt,
case TSDB_ALTER_TABLE_UPDATE_OPTIONS: case TSDB_ALTER_TABLE_UPDATE_OPTIONS:
return buildUpdateOptionsReq(pCxt, pStmt, pReq); return buildUpdateOptionsReq(pCxt, pStmt, pReq);
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME: case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
return buildRenameColReq(pCxt, pStmt, pTableMeta, pReq); if (TSDB_CHILD_TABLE == pTableMeta->tableType) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
} else {
return buildRenameColReq(pCxt, pStmt, pTableMeta, pReq);
}
default: default:
break; break;
} }
......
...@@ -76,7 +76,7 @@ static char* getSyntaxErrFormat(int32_t errCode) { ...@@ -76,7 +76,7 @@ static char* getSyntaxErrFormat(int32_t errCode) {
case TSDB_CODE_PAR_INVALID_KEEP_ORDER: case TSDB_CODE_PAR_INVALID_KEEP_ORDER:
return "Invalid keep value, should be keep0 <= keep1 <= keep2"; return "Invalid keep value, should be keep0 <= keep1 <= keep2";
case TSDB_CODE_PAR_INVALID_KEEP_VALUE: case TSDB_CODE_PAR_INVALID_KEEP_VALUE:
return "Invalid option keep: %d, %d, %d valid range: [%d, %d]"; return "Invalid option keep: %" PRId64 ", %" PRId64 ", %" PRId64 " valid range: [%dm, %dm]";
case TSDB_CODE_PAR_INVALID_COMMENT_OPTION: case TSDB_CODE_PAR_INVALID_COMMENT_OPTION:
return "Invalid option comment, length cannot exceed %d"; return "Invalid option comment, length cannot exceed %d";
case TSDB_CODE_PAR_INVALID_F_RANGE_OPTION: case TSDB_CODE_PAR_INVALID_F_RANGE_OPTION:
...@@ -182,6 +182,8 @@ static char* getSyntaxErrFormat(int32_t errCode) { ...@@ -182,6 +182,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
return "The DELETE statement must have a definite time window range"; return "The DELETE statement must have a definite time window range";
case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG: case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes"; return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
return "%s function not allowed in fill query";
case TSDB_CODE_OUT_OF_MEMORY: case TSDB_CODE_OUT_OF_MEMORY:
return "Out of memory"; return "Out of memory";
default: default:
......
...@@ -24,7 +24,7 @@ class ParserInitialATest : public ParserDdlTest {}; ...@@ -24,7 +24,7 @@ class ParserInitialATest : public ParserDdlTest {};
TEST_F(ParserInitialATest, alterAccount) { TEST_F(ParserInitialATest, alterAccount) {
useDb("root", "test"); useDb("root", "test");
run("ALTER ACCOUNT ac_wxy PASS '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT); run("ALTER ACCOUNT ac_wxy PASS '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT, PARSER_STAGE_PARSE);
} }
TEST_F(ParserInitialATest, alterDnode) { TEST_F(ParserInitialATest, alterDnode) {
...@@ -157,8 +157,8 @@ TEST_F(ParserInitialATest, alterSTable) { ...@@ -157,8 +157,8 @@ TEST_F(ParserInitialATest, alterSTable) {
20 + VARSTR_HEADER_SIZE); 20 + VARSTR_HEADER_SIZE);
run("ALTER TABLE st1 MODIFY COLUMN c1 VARCHAR(20)"); run("ALTER TABLE st1 MODIFY COLUMN c1 VARCHAR(20)");
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, 2, "c1", 0, 0, "cc1"); // setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, 2, "c1", 0, 0, "cc1");
run("ALTER TABLE st1 RENAME COLUMN c1 cc1"); // run("ALTER TABLE st1 RENAME COLUMN c1 cc1");
setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_ADD_TAG, 1, "tag11", TSDB_DATA_TYPE_BIGINT); setAlterStbReqFunc("st1", TSDB_ALTER_TABLE_ADD_TAG, 1, "tag11", TSDB_DATA_TYPE_BIGINT);
run("ALTER TABLE st1 ADD TAG tag11 BIGINT"); run("ALTER TABLE st1 ADD TAG tag11 BIGINT");
...@@ -177,6 +177,12 @@ TEST_F(ParserInitialATest, alterSTable) { ...@@ -177,6 +177,12 @@ TEST_F(ParserInitialATest, alterSTable) {
// ADD {FULLTEXT | SMA} INDEX index_name (col_name [, col_name] ...) [index_option] // ADD {FULLTEXT | SMA} INDEX index_name (col_name [, col_name] ...) [index_option]
} }
TEST_F(ParserInitialATest, alterSTableSemanticCheck) {
useDb("root", "test");
run("ALTER TABLE st1 RENAME COLUMN c1 cc1", TSDB_CODE_PAR_INVALID_ALTER_TABLE);
}
TEST_F(ParserInitialATest, alterTable) { TEST_F(ParserInitialATest, alterTable) {
useDb("root", "test"); useDb("root", "test");
...@@ -299,6 +305,12 @@ TEST_F(ParserInitialATest, alterTable) { ...@@ -299,6 +305,12 @@ TEST_F(ParserInitialATest, alterTable) {
// ADD {FULLTEXT | SMA} INDEX index_name (col_name [, col_name] ...) [index_option] // ADD {FULLTEXT | SMA} INDEX index_name (col_name [, col_name] ...) [index_option]
} }
TEST_F(ParserInitialATest, alterTableSemanticCheck) {
useDb("root", "test");
run("ALTER TABLE st1s1 RENAME COLUMN c1 cc1", TSDB_CODE_PAR_INVALID_ALTER_TABLE);
}
TEST_F(ParserInitialATest, alterUser) { TEST_F(ParserInitialATest, alterUser) {
useDb("root", "test"); useDb("root", "test");
...@@ -323,7 +335,7 @@ TEST_F(ParserInitialATest, balanceVgroup) { ...@@ -323,7 +335,7 @@ TEST_F(ParserInitialATest, balanceVgroup) {
TEST_F(ParserInitialATest, bug001) { TEST_F(ParserInitialATest, bug001) {
useDb("root", "test"); useDb("root", "test");
run("ALTER DATABASE db WAL 0 # td-14436", TSDB_CODE_PAR_SYNTAX_ERROR); run("ALTER DATABASE db WAL 0 # td-14436", TSDB_CODE_PAR_SYNTAX_ERROR, PARSER_STAGE_PARSE);
} }
} // namespace ParserTest } // namespace ParserTest
\ No newline at end of file
...@@ -27,7 +27,7 @@ class ParserInitialCTest : public ParserDdlTest {}; ...@@ -27,7 +27,7 @@ class ParserInitialCTest : public ParserDdlTest {};
TEST_F(ParserInitialCTest, createAccount) { TEST_F(ParserInitialCTest, createAccount) {
useDb("root", "test"); useDb("root", "test");
run("CREATE ACCOUNT ac_wxy PASS '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT); run("CREATE ACCOUNT ac_wxy PASS '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT, PARSER_STAGE_PARSE);
} }
TEST_F(ParserInitialCTest, createBnode) { TEST_F(ParserInitialCTest, createBnode) {
...@@ -186,7 +186,7 @@ TEST_F(ParserInitialCTest, createDatabase) { ...@@ -186,7 +186,7 @@ TEST_F(ParserInitialCTest, createDatabase) {
setDbReplicaFunc(3); setDbReplicaFunc(3);
addDbRetentionFunc(15 * MILLISECOND_PER_SECOND, 7 * MILLISECOND_PER_DAY, TIME_UNIT_SECOND, TIME_UNIT_DAY); addDbRetentionFunc(15 * MILLISECOND_PER_SECOND, 7 * MILLISECOND_PER_DAY, TIME_UNIT_SECOND, TIME_UNIT_DAY);
addDbRetentionFunc(1 * MILLISECOND_PER_MINUTE, 21 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); addDbRetentionFunc(1 * MILLISECOND_PER_MINUTE, 21 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY);
addDbRetentionFunc(15 * MILLISECOND_PER_MINUTE, 5, TIME_UNIT_MINUTE, TIME_UNIT_YEAR); addDbRetentionFunc(15 * MILLISECOND_PER_MINUTE, 500 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY);
setDbStrictaFunc(1); setDbStrictaFunc(1);
setDbWalLevelFunc(2); setDbWalLevelFunc(2);
setDbVgroupsFunc(100); setDbVgroupsFunc(100);
...@@ -205,7 +205,7 @@ TEST_F(ParserInitialCTest, createDatabase) { ...@@ -205,7 +205,7 @@ TEST_F(ParserInitialCTest, createDatabase) {
"PAGESIZE 8 " "PAGESIZE 8 "
"PRECISION 'ns' " "PRECISION 'ns' "
"REPLICA 3 " "REPLICA 3 "
"RETENTIONS 15s:7d,1m:21d,15m:5y " "RETENTIONS 15s:7d,1m:21d,15m:500d "
"STRICT 1 " "STRICT 1 "
"WAL 2 " "WAL 2 "
"VGROUPS 100 " "VGROUPS 100 "
...@@ -220,6 +220,17 @@ TEST_F(ParserInitialCTest, createDatabase) { ...@@ -220,6 +220,17 @@ TEST_F(ParserInitialCTest, createDatabase) {
"KEEP 1440m,300h,400d "); "KEEP 1440m,300h,400d ");
} }
TEST_F(ParserInitialCTest, createDatabaseSemanticCheck) {
useDb("root", "test");
run("create database db2 retentions 0s:1d", TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
run("create database db2 retentions 10s:0d", TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
run("create database db2 retentions 1w:1d", TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
run("create database db2 retentions 1w:1n", TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
run("create database db2 retentions 15s:7d,15m:21d,10m:500d", TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
run("create database db2 retentions 15s:7d,5m:21d,10m:10d", TSDB_CODE_PAR_INVALID_RETENTIONS_OPTION);
}
TEST_F(ParserInitialCTest, createDnode) { TEST_F(ParserInitialCTest, createDnode) {
useDb("root", "test"); useDb("root", "test");
...@@ -434,6 +445,13 @@ TEST_F(ParserInitialCTest, createStable) { ...@@ -434,6 +445,13 @@ TEST_F(ParserInitialCTest, createStable) {
"TTL 100 COMMENT 'test create table' SMA(c1, c2, c3) ROLLUP (MIN) FILE_FACTOR 0.1"); "TTL 100 COMMENT 'test create table' SMA(c1, c2, c3) ROLLUP (MIN) FILE_FACTOR 0.1");
} }
TEST_F(ParserInitialCTest, createStableSemanticCheck) {
useDb("root", "test");
run("CREATE STABLE stb2 (ts TIMESTAMP, c1 INT) TAGS (tag1 INT) ROLLUP(CEIL) FILE_FACTOR 0.1",
TSDB_CODE_PAR_INVALID_ROLLUP_OPTION, PARSER_STAGE_TRANSLATE);
}
TEST_F(ParserInitialCTest, createStream) { TEST_F(ParserInitialCTest, createStream) {
useDb("root", "test"); useDb("root", "test");
......
...@@ -65,6 +65,8 @@ TEST_F(ParserSelectTest, condition) { ...@@ -65,6 +65,8 @@ TEST_F(ParserSelectTest, condition) {
run("SELECT c1 FROM t1 WHERE ts in (true, false)"); run("SELECT c1 FROM t1 WHERE ts in (true, false)");
run("SELECT c1 FROM t1 WHERE NOT ts in (true, false)");
run("SELECT * FROM t1 WHERE c1 > 10 and c1 is not null"); run("SELECT * FROM t1 WHERE c1 > 10 and c1 is not null");
} }
...@@ -212,9 +214,11 @@ TEST_F(ParserSelectTest, interval) { ...@@ -212,9 +214,11 @@ TEST_F(ParserSelectTest, interval) {
TEST_F(ParserSelectTest, intervalSemanticCheck) { TEST_F(ParserSelectTest, intervalSemanticCheck) {
useDb("root", "test"); useDb("root", "test");
run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE); run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
run("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 3 INTERVAL(1d) FILL(NEXT)", TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE, run("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 3 INTERVAL(1d) FILL(NEXT)", TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE);
PARSER_STAGE_TRANSLATE); run("SELECT HISTOGRAM(c1, 'log_bin', '{\"start\": -33,\"factor\": 55,\"count\": 5,\"infinity\": false}', 1) FROM t1 "
"WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' INTERVAL(10s) FILL(NULL)",
TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC);
} }
TEST_F(ParserSelectTest, subquery) { TEST_F(ParserSelectTest, subquery) {
......
...@@ -36,7 +36,7 @@ class ParserTestBase : public testing::Test { ...@@ -36,7 +36,7 @@ class ParserTestBase : public testing::Test {
void login(const std::string& user); void login(const std::string& user);
void useDb(const std::string& acctId, const std::string& db); void useDb(const std::string& acctId, const std::string& db);
void run(const std::string& sql, int32_t expect = TSDB_CODE_SUCCESS, ParserStage checkStage = PARSER_STAGE_ALL); void run(const std::string& sql, int32_t expect = TSDB_CODE_SUCCESS, ParserStage checkStage = PARSER_STAGE_TRANSLATE);
virtual void checkDdl(const SQuery* pQuery, ParserStage stage); virtual void checkDdl(const SQuery* pQuery, ParserStage stage);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册