From b57f62f139919c6521e3494ae151b3e3c6624987 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Thu, 12 May 2022 20:33:52 +0800 Subject: [PATCH] feat: adjust query stmt APIs --- include/libs/nodes/querynodes.h | 1 + include/libs/parser/parser.h | 18 ++-- source/client/src/clientImpl.c | 6 +- source/libs/parser/inc/parAst.h | 1 + source/libs/parser/src/parAstCreater.c | 8 ++ source/libs/parser/src/parAstParser.c | 2 + source/libs/parser/src/parser.c | 115 +++++++++++++++++++++- source/libs/planner/test/planTestUtil.cpp | 2 +- 8 files changed, 138 insertions(+), 15 deletions(-) diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index d07f29c487..8232dbba0f 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -324,6 +324,7 @@ typedef struct SQuery { SArray* pTableList; bool showRewrite; int32_t placeholderNum; + SArray* pPlaceholderValues; } SQuery; void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 61e4bb3723..ca399a0235 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -47,21 +47,23 @@ typedef struct SParseContext { bool isSuperUser; } SParseContext; -int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery); +int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery); bool isInsertSql(const char* pStr, size_t length); void qDestroyQuery(SQuery* pQueryNode); int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema); -int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash); -int32_t qResetStmtDataBlock(void* block, bool keepBuf); -int32_t qCloneStmtDataBlock(void** pDst, void* pSrc); -void qFreeStmtDataBlock(void* pDataBlock); -int32_t qRebuildStmtDataBlock(void** pDst, void* pSrc, uint64_t uid, int32_t vgId); -void qDestroyStmtDataBlock(void* pBlock); -STableMeta *qGetTableMetaInDataBlock(void* pDataBlock); +int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash); +int32_t qResetStmtDataBlock(void* block, bool keepBuf); +int32_t qCloneStmtDataBlock(void** pDst, void* pSrc); +void qFreeStmtDataBlock(void* pDataBlock); +int32_t qRebuildStmtDataBlock(void** pDst, void* pSrc, uint64_t uid, int32_t vgId); +void qDestroyStmtDataBlock(void* pBlock); +STableMeta* qGetTableMetaInDataBlock(void* pDataBlock); +int32_t qStmtBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx, uint64_t queryId); +int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery); int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen); int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen, int32_t colIdx, int32_t rowNum); diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index cb361f09a6..f879838d63 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -180,7 +180,7 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC return code; } - code = qParseQuerySql(&cxt, pQuery); + code = qParseSql(&cxt, pQuery); if (TSDB_CODE_SUCCESS == code) { if ((*pQuery)->haveResultSet) { setResSchemaInfo(&pRequest->body.resInfo, (*pQuery)->pResSchema, (*pQuery)->numOfResCols); @@ -554,8 +554,8 @@ static SMsgSendInfo* buildConnectMsg(SRequestObj* pRequest) { } taosMemoryFreeClear(db); - connectReq.connType = pObj->connType; - connectReq.pid = htonl(appInfo.pid); + connectReq.connType = pObj->connType; + connectReq.pid = htonl(appInfo.pid); connectReq.startTime = htobe64(appInfo.startTime); tstrncpy(connectReq.app, appInfo.appName, sizeof(connectReq.app)); diff --git a/source/libs/parser/inc/parAst.h b/source/libs/parser/inc/parAst.h index b15078157a..fc096a057c 100644 --- a/source/libs/parser/inc/parAst.h +++ b/source/libs/parser/inc/parAst.h @@ -32,6 +32,7 @@ typedef struct SAstCreateContext { bool notSupport; SNode* pRootNode; int16_t placeholderNo; + SArray* pPlaceholderValues; int32_t errCode; } SAstCreateContext; diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index 74a023f0cd..b0930f69d4 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -299,6 +299,14 @@ SNode* createPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLitera val->literal = strndup(pLiteral->z, pLiteral->n); CHECK_OUT_OF_MEM(val->literal); val->placeholderNo = ++pCxt->placeholderNo; + if (NULL == pCxt->pPlaceholderValues) { + pCxt->pPlaceholderValues = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); + if (NULL == pCxt->pPlaceholderValues) { + nodesDestroyNode(val); + return NULL; + } + } + taosArrayPush(pCxt->pPlaceholderValues, &val); return (SNode*)val; } diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index ebc8281f56..5b59d1c080 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -81,6 +81,8 @@ abort_parse: } (*pQuery)->pRoot = cxt.pRootNode; (*pQuery)->placeholderNum = cxt.placeholderNo; + TSWAP((*pQuery)->pPlaceholderValues, cxt.pPlaceholderValues); } + taosArrayDestroy(cxt.pPlaceholderValues); return cxt.errCode; } diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index bc98a41923..2652078b96 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -39,16 +39,99 @@ static int32_t parseSqlIntoAst(SParseContext* pCxt, SQuery** pQuery) { if (TSDB_CODE_SUCCESS == code) { code = authenticate(pCxt, *pQuery); } - if (TSDB_CODE_SUCCESS == code) { + if (TSDB_CODE_SUCCESS == code && 0 == (*pQuery)->placeholderNum) { code = translate(pCxt, *pQuery); } - if (TSDB_CODE_SUCCESS == code) { + if (TSDB_CODE_SUCCESS == code && 0 == (*pQuery)->placeholderNum) { code = calculateConstant(pCxt, *pQuery); } return code; } -int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery) { +static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) { + if (pParam->is_null && 1 == *(pParam->is_null)) { + pVal->node.resType.type = TSDB_DATA_TYPE_NULL; + pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes; + return TSDB_CODE_SUCCESS; + } + int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes); + pVal->node.resType.type = pParam->buffer_type; + pVal->node.resType.bytes = inputSize; + switch (pParam->buffer_type) { + case TSDB_DATA_TYPE_BOOL: + pVal->datum.b = *((bool*)pParam->buffer); + break; + case TSDB_DATA_TYPE_TINYINT: + pVal->datum.i = *((int8_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_SMALLINT: + pVal->datum.i = *((int16_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_INT: + pVal->datum.i = *((int32_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_BIGINT: + pVal->datum.i = *((int64_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_FLOAT: + pVal->datum.d = *((float*)pParam->buffer); + break; + case TSDB_DATA_TYPE_DOUBLE: + pVal->datum.d = *((double*)pParam->buffer); + break; + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_VARBINARY: + pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1); + if (NULL == pVal->datum.p) { + return TSDB_CODE_OUT_OF_MEMORY; + } + varDataSetLen(pVal->datum.p, pVal->node.resType.bytes); + strncpy(varDataVal(pVal->datum.p), (const char*)pParam->buffer, pVal->node.resType.bytes); + break; + case TSDB_DATA_TYPE_NCHAR: { + pVal->node.resType.bytes *= TSDB_NCHAR_SIZE; + pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1); + if (NULL == pVal->datum.p) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + int32_t output = 0; + if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes, + &output)) { + return errno; + } + varDataSetLen(pVal->datum.p, output); + pVal->node.resType.bytes = output; + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + pVal->datum.i = *((int64_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_UTINYINT: + pVal->datum.u = *((uint8_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_USMALLINT: + pVal->datum.u = *((uint16_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_UINT: + pVal->datum.u = *((uint32_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_UBIGINT: + pVal->datum.u = *((uint64_t*)pParam->buffer); + break; + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: + // todo + default: + break; + } + pVal->translate = true; + return TSDB_CODE_SUCCESS; +} + +int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) { int32_t code = TSDB_CODE_SUCCESS; if (isInsertSql(pCxt->pSql, pCxt->sqlLen)) { code = parseInsertSql(pCxt, pQuery); @@ -77,3 +160,29 @@ void qDestroyQuery(SQuery* pQueryNode) { int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) { return extractResultSchema(pRoot, numOfCols, pSchema); } + +int32_t qStmtBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx, uint64_t queryId) { + int32_t code = TSDB_CODE_SUCCESS; + + if (colIdx < 0) { + int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues); + for (int32_t i = 0; i < size; ++i) { + code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + } else { + code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams); + } + + return code; +} + +int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery) { + int32_t code = translate(pCxt, pQuery); + if (TSDB_CODE_SUCCESS == code) { + code = calculateConstant(pCxt, pQuery); + } + return code; +} diff --git a/source/libs/planner/test/planTestUtil.cpp b/source/libs/planner/test/planTestUtil.cpp index e434a6be96..b2c590667e 100644 --- a/source/libs/planner/test/planTestUtil.cpp +++ b/source/libs/planner/test/planTestUtil.cpp @@ -198,7 +198,7 @@ class PlannerTestBaseImpl { cxt.pMsg = stmtEnv_.msgBuf_.data(); cxt.msgLen = stmtEnv_.msgBuf_.max_size(); - DO_WITH_THROW(qParseQuerySql, &cxt, pQuery); + DO_WITH_THROW(qParseSql, &cxt, pQuery); res_.ast_ = toString((*pQuery)->pRoot); } -- GitLab