From 77ff634df80e4bfd17b851db51e04eb2fcf23651 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 14 Dec 2021 15:51:57 +0800 Subject: [PATCH 1/4] [td-10564] enable parser create user. --- include/libs/parser/parser.h | 2 +- source/client/CMakeLists.txt | 2 +- source/client/inc/clientInt.h | 7 ++- source/client/inc/{tscLog.h => clientLog.h} | 4 +- source/client/src/client.c | 4 +- source/client/src/clientImpl.c | 60 ++++++++++++++++++- .../client/src/{clientmain.c => clientMain.c} | 14 ++++- source/client/src/clientMsgHandler.c | 4 +- source/client/src/tscEnv.c | 7 ++- source/client/test/clientTests.cpp | 1 + source/libs/parser/src/parser.c | 19 ++++-- 11 files changed, 100 insertions(+), 24 deletions(-) rename source/client/inc/{tscLog.h => clientLog.h} (96%) rename source/client/src/{clientmain.c => clientMain.c} (90%) diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 2f152c3e2b..f114690423 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -151,7 +151,7 @@ typedef struct SParseContext { * @param msg extended error message if exists. * @return error code */ -int32_t qParseQuerySql(const char* pStr, size_t length, struct SQueryStmtInfo** pQueryInfo, int64_t id, char* msg, int32_t msgLen); +struct SQueryStmtInfo* qParseQuerySql(const char* pStr, size_t length, int64_t id, char* msg, int32_t msgLen); typedef enum { PAYLOAD_TYPE_KV = 0, diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 1a67faea9f..b916d26dd2 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -8,7 +8,7 @@ target_include_directories( target_link_libraries( taos INTERFACE api - PRIVATE os util common transport parser + PRIVATE os util common transport parser catalog function ) ADD_SUBDIRECTORY(test) \ No newline at end of file diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 3180923aff..c0d2506424 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -92,6 +92,8 @@ typedef struct SReqBody { void* param; } SRequestBody; +#define ERROR_MSG_BUF_DEFAULT_SIZE 512 + typedef struct SRequestObj { uint64_t requestId; int32_t type; // request type @@ -129,8 +131,6 @@ void destroyTscObj(void*pObj); void* createRequest(STscObj* pObj, __taos_async_fn_t fp, void* param, int32_t type); void destroyRequest(SRequestObj* pRequest); -TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, const char *auth, const char *db, uint16_t port); - void taos_init_imp(void); int taos_options_imp(TSDB_OPTION option, const char *str); @@ -139,6 +139,9 @@ void* openTransporter(const char *user, const char *auth); void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet); void initMsgHandleFp(); +TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, const char *auth, const char *db, uint16_t port); +TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen); + #ifdef __cplusplus } #endif diff --git a/source/client/inc/tscLog.h b/source/client/inc/clientLog.h similarity index 96% rename from source/client/inc/tscLog.h rename to source/client/inc/clientLog.h index f205a50227..bfa2c0319b 100644 --- a/source/client/inc/tscLog.h +++ b/source/client/inc/clientLog.h @@ -13,8 +13,8 @@ * along with this program. If not, see . */ -#ifndef TDENGINE_TSCLOG_H -#define TDENGINE_TSCLOG_H +#ifndef TDENGINE_CLIENTLOG_H +#define TDENGINE_CLIENTLOG_H #ifdef __cplusplus extern "C" { diff --git a/source/client/src/client.c b/source/client/src/client.c index a99c7c44bc..1dbfe76a3f 100644 --- a/source/client/src/client.c +++ b/source/client/src/client.c @@ -16,9 +16,9 @@ #include "os.h" #include "tdef.h" -#include "tglobal.h" #include "clientInt.h" -#include "tscLog.h" +#include "clientLog.h" +#include "tglobal.h" TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) { int32_t p = (port != 0)? port:tsServerPort; diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 2ae79f1947..19a3ac2d64 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1,11 +1,14 @@ -#include + +#include #include "clientInt.h" +#include "clientLog.h" #include "tdef.h" #include "tep.h" #include "tglobal.h" #include "tmsgtype.h" +#include "tnote.h" +#include "tpagedfile.h" #include "tref.h" -#include "tscLog.h" static int32_t initEpSetFromCfg(const char *firstEp, const char *secondEp, SCorEpSet *pEpSet); static int32_t buildConnectMsg(SRequestObj *pRequest, SRequestMsgBody* pMsgBody); @@ -109,6 +112,59 @@ TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, return taosConnectImpl(ip, user, &secretEncrypt[0], db, port, NULL, NULL, pInst); } +TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen) { + STscObj *pObj = (STscObj *)taos; + if (sqlLen > (size_t) tsMaxSQLStringLen) { + tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); + terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; + return NULL; + } + + nPrintTsc("%s", sql) + + SRequestObj* pRequest = createRequest(pObj, NULL, NULL, TSDB_SQL_SELECT); + if (pRequest == NULL) { + tscError("failed to malloc sqlObj"); + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; + return NULL; + } + + pRequest->sqlstr = malloc(sqlLen + 1); + if (pRequest->sqlstr == NULL) { + tscError("0x%"PRIx64" failed to prepare sql string buffer", pRequest->self); + + pRequest->msgBuf = strdup("failed to prepare sql string buffer"); + terrno = pRequest->code = TSDB_CODE_TSC_OUT_OF_MEMORY; + return pRequest; + } + + strntolower(pRequest->sqlstr, sql, (int32_t)sqlLen); + pRequest->sqlstr[sqlLen] = 0; + + tscDebugL("0x%"PRIx64" SQL: %s", pRequest->requestId, pRequest->sqlstr); + + int32_t code = 0;//tsParseSql(pSql, true); + if (qIsInsertSql(pRequest->sqlstr, sqlLen)) { +// qParseInsertSql(); + } else { + SQueryStmtInfo *pQueryInfo = qParseQuerySql(pRequest->sqlstr, sqlLen, pRequest->requestId, pRequest->msgBuf, ERROR_MSG_BUF_DEFAULT_SIZE); + assert(pQueryInfo != NULL); + } + + if (code != TSDB_CODE_SUCCESS) { + pRequest->code = code; +// tscAsyncResultOnError(pSql); +// taosReleaseRef(tscReqRef, p->self); + return NULL; + } + +// executeQuery(pSql, pQueryInfo); +// doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen); + + tsem_wait(&pRequest->body.rspSem); + return pRequest; +} + int initEpSetFromCfg(const char *firstEp, const char *secondEp, SCorEpSet *pEpSet) { pEpSet->version = 0; diff --git a/source/client/src/clientmain.c b/source/client/src/clientMain.c similarity index 90% rename from source/client/src/clientmain.c rename to source/client/src/clientMain.c index ba80135850..b039130433 100644 --- a/source/client/src/clientmain.c +++ b/source/client/src/clientMain.c @@ -1,5 +1,5 @@ #include "clientInt.h" -#include "trpc.h" +#include "clientLog.h" #include "os.h" #include "taosmsg.h" #include "tcache.h" @@ -7,7 +7,7 @@ #include "tglobal.h" #include "tnote.h" #include "tref.h" -#include "tscLog.h" +#include "trpc.h" #include "tsched.h" #include "ttime.h" #include "ttimezone.h" @@ -82,4 +82,12 @@ const char *taos_errstr(TAOS_RES *res) { void taos_free_result(TAOS_RES *res) { -} \ No newline at end of file +} + +TAOS_RES *taos_query(TAOS *taos, const char *sql) { + if (taos == NULL || sql == NULL) { + return NULL; + } + + return taos_query_l(taos, sql, strlen(sql)); +} diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c index 62466a096d..606397dc78 100644 --- a/source/client/src/clientMsgHandler.c +++ b/source/client/src/clientMsgHandler.c @@ -13,11 +13,11 @@ * along with this program. If not, see . */ -#include "os.h" #include "clientInt.h" +#include "clientLog.h" +#include "os.h" #include "tmsgtype.h" #include "trpc.h" -#include "tscLog.h" int (*buildRequestMsgFp[TSDB_SQL_MAX])(SRequestObj *pRequest, SRequestMsgBody *pMsgBody) = {0}; int (*handleRequestRspFp[TSDB_SQL_MAX])(SRequestObj *pRequest, const char* pMsg, int32_t msgLen); diff --git a/source/client/src/tscEnv.c b/source/client/src/tscEnv.c index 43d73bf3db..0e9be4af49 100644 --- a/source/client/src/tscEnv.c +++ b/source/client/src/tscEnv.c @@ -13,6 +13,8 @@ * along with this program. If not, see . */ +#include "clientInt.h" +#include "clientLog.h" #include "os.h" #include "taosmsg.h" #include "tcache.h" @@ -20,12 +22,10 @@ #include "tglobal.h" #include "tnote.h" #include "tref.h" -#include "tscLog.h" +#include "trpc.h" #include "tsched.h" #include "ttime.h" -#include "trpc.h" #include "ttimezone.h" -#include "clientInt.h" #define TSC_VAR_NOT_RELEASE 1 #define TSC_VAR_RELEASED 0 @@ -172,6 +172,7 @@ void* createRequest(STscObj* pObj, __taos_async_fn_t fp, void* param, int32_t ty pRequest->pTscObj = pObj; pRequest->body.fp = fp; pRequest->body.param = param; + pRequest->msgBuf = calloc(1, ERROR_MSG_BUF_DEFAULT_SIZE); tsem_init(&pRequest->body.rspSem, 0, 0); registerRequest(pRequest); diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index 8da4caf7eb..6f371dbd12 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -36,5 +36,6 @@ TEST(testCase, driverInit_Test) { TAOS* pConn = taos_connect("ubuntu", "root", "taosdata", NULL, 0); assert(pConn != NULL); + taos_query(pConn, "create user abc pass 'abc'"); taos_close(pConn); } \ No newline at end of file diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index a8642e2535..42d6fc1c5e 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -31,20 +31,27 @@ bool qIsInsertSql(const char* pStr, size_t length) { } while (1); } -int32_t qParseQuerySql(const char* pStr, size_t length, struct SQueryStmtInfo** pQueryInfo, int64_t id, char* msg, int32_t msgLen) { - *pQueryInfo = calloc(1, sizeof(SQueryStmtInfo)); - if (*pQueryInfo == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; // set correct error code. +SQueryStmtInfo* qParseQuerySql(const char* pStr, size_t length, int64_t id, char* msg, int32_t msgLen) { + SQueryStmtInfo* pQueryInfo = calloc(1, sizeof(SQueryStmtInfo)); + if (pQueryInfo == NULL) { + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; // set correct error code. + return NULL; } SSqlInfo info = doGenerateAST(pStr); if (!info.valid) { strncpy(msg, info.msg, msgLen); - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; + terrno = TSDB_CODE_TSC_SQL_SYNTAX_ERROR; + return NULL; } struct SCatalog* pCatalog = getCatalogHandle(NULL); - return qParserValidateSqlNode(pCatalog, &info, *pQueryInfo, id, msg, msgLen); + int32_t code = qParserValidateSqlNode(pCatalog, &info, pQueryInfo, id, msg, msgLen); + if (code == TSDB_CODE_SUCCESS) { + return pQueryInfo; + } + + return NULL; } int32_t qParseInsertSql(SParseContext* pContext, SInsertStmtInfo** pInfo) { From 638691728754bbb663f8abb409213d4cb0f03958 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 15 Dec 2021 19:34:36 +0800 Subject: [PATCH 2/4] [td-11818] support create user/show user parser. --- .devcontainer/Dockerfile | 9 ++ .devcontainer/devcontainer.json | 32 +++++ include/common/taosmsg.h | 2 + include/libs/parser/parser.h | 2 +- include/util/tdef.h | 1 + source/client/inc/clientInt.h | 2 +- source/client/src/client.c | 64 --------- source/client/src/clientImpl.c | 70 +++++++--- source/client/src/clientMain.c | 46 +++++-- source/client/src/clientMsgHandler.c | 54 +++++++- source/client/src/tscEnv.c | 8 +- source/client/test/clientTests.cpp | 11 +- source/libs/parser/inc/parserInt.h | 9 ++ source/libs/parser/inc/parserUtil.h | 4 + source/libs/parser/src/astValidate.c | 173 +++++++++++++----------- source/libs/parser/src/parser.c | 24 ++-- source/libs/parser/src/parserUtil.c | 45 +++--- source/libs/parser/test/parserTests.cpp | 45 ++++++ 18 files changed, 398 insertions(+), 203 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json delete mode 100644 source/client/src/client.c diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..fc9a51af65 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,9 @@ +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.209.3/containers/cpp/.devcontainer/base.Dockerfile + +# [Choice] Debian / Ubuntu version (use Debian 11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 +ARG VARIANT="bullseye" +FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT} + +# [Optional] Uncomment this section to install additional packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..9b752d091d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,32 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.3/containers/cpp +{ + "name": "C++", + "build": { + "dockerfile": "Dockerfile", + // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 + // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon + "args": { "VARIANT": "ubuntu-21.04" } + }, + "runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"], + + // Set *default* container specific settings.json values on container create. + "settings": {}, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools", + "austin.code-gnu-global", + "visualstudioexptteam.vscodeintel" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "gcc -v", + + // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" +} diff --git a/include/common/taosmsg.h b/include/common/taosmsg.h index 45f9514cf0..1d44255f6d 100644 --- a/include/common/taosmsg.h +++ b/include/common/taosmsg.h @@ -393,8 +393,10 @@ typedef struct { } SDropUserMsg, SDropAcctMsg; typedef struct { + int8_t type; char user[TSDB_USER_LEN]; char pass[TSDB_PASSWORD_LEN]; + int8_t superUser; // denote if it is a super user or not } SCreateUserMsg, SAlterUserMsg; typedef struct { diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index f114690423..c766bd99b2 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -151,7 +151,7 @@ typedef struct SParseContext { * @param msg extended error message if exists. * @return error code */ -struct SQueryStmtInfo* qParseQuerySql(const char* pStr, size_t length, int64_t id, char* msg, int32_t msgLen); +int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t* type, void** pOutput, char* msg, int32_t msgLen); typedef enum { PAYLOAD_TYPE_KV = 0, diff --git a/include/util/tdef.h b/include/util/tdef.h index 300b190e97..7f5ebaee57 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -194,6 +194,7 @@ do { \ #define TSDB_AUTH_LEN 16 #define TSDB_PASSWORD_LEN 32 +#define TSDB_USET_PASSWORD_LEN 129 #define TSDB_VERSION_LEN 12 #define TSDB_LABEL_LEN 8 diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index c0d2506424..64dce1e5b1 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -120,7 +120,7 @@ extern int32_t tscReqRef; extern void *tscQhandle; extern int32_t tscConnRef; -extern int (*tscBuildMsg[TSDB_SQL_MAX])(SRequestObj *pRequest, SRequestMsgBody *pMsg); +extern int (*buildRequestMsgFp[TSDB_SQL_MAX])(SRequestObj *pRequest, SRequestMsgBody *pMsgBody); extern int (*handleRequestRspFp[TSDB_SQL_MAX])(SRequestObj *pRequest, const char* pMsg, int32_t msgLen); int taos_init(); diff --git a/source/client/src/client.c b/source/client/src/client.c deleted file mode 100644 index 1dbfe76a3f..0000000000 --- a/source/client/src/client.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "os.h" -#include "tdef.h" - -#include "clientInt.h" -#include "clientLog.h" -#include "tglobal.h" - -TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) { - int32_t p = (port != 0)? port:tsServerPort; - - tscDebug("try to connect to %s:%u, user:%s db:%s", ip, p, user, db); - if (user == NULL) { - user = TSDB_DEFAULT_USER; - } - - if (pass == NULL) { - pass = TSDB_DEFAULT_PASS; - } - - return taos_connect_internal(ip, user, pass, NULL, db, p); -} - -TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port) { - tscDebug("try to connect to %s:%u by auth, user:%s db:%s", ip, port, user, db); - if (user == NULL) { - user = TSDB_DEFAULT_USER; - } - - if (auth == NULL) { - tscError("No auth info is given, failed to connect to server"); - return NULL; - } - - return taos_connect_internal(ip, user, NULL, auth, db, port); -} - -TAOS *taos_connect_l(const char *ip, int ipLen, const char *user, int userLen, const char *pass, int passLen, const char *db, int dbLen, uint16_t port) { - char ipStr[TSDB_EP_LEN] = {0}; - char dbStr[TSDB_DB_NAME_LEN] = {0}; - char userStr[TSDB_USER_LEN] = {0}; - char passStr[TSDB_PASSWORD_LEN] = {0}; - - strncpy(ipStr, ip, MIN(TSDB_EP_LEN - 1, ipLen)); - strncpy(userStr, user, MIN(TSDB_USER_LEN - 1, userLen)); - strncpy(passStr, pass, MIN(TSDB_PASSWORD_LEN - 1, passLen)); - strncpy(dbStr, db, MIN(TSDB_DB_NAME_LEN - 1, dbLen)); - return taos_connect(ipStr, userStr, passStr, dbStr, port); -} - diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 19a3ac2d64..a0b7d5e9a7 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1,5 +1,4 @@ -#include #include "clientInt.h" #include "clientLog.h" #include "tdef.h" @@ -9,6 +8,7 @@ #include "tnote.h" #include "tpagedfile.h" #include "tref.h" +#include "parser.h" static int32_t initEpSetFromCfg(const char *firstEp, const char *secondEp, SCorEpSet *pEpSet); static int32_t buildConnectMsg(SRequestObj *pRequest, SRequestMsgBody* pMsgBody); @@ -113,7 +113,7 @@ TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, } TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen) { - STscObj *pObj = (STscObj *)taos; + STscObj *pTscObj = (STscObj *)taos; if (sqlLen > (size_t) tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; @@ -122,7 +122,7 @@ TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen) { nPrintTsc("%s", sql) - SRequestObj* pRequest = createRequest(pObj, NULL, NULL, TSDB_SQL_SELECT); + SRequestObj* pRequest = createRequest(pTscObj, NULL, NULL, TSDB_SQL_SELECT); if (pRequest == NULL) { tscError("failed to malloc sqlObj"); terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; @@ -143,25 +143,36 @@ TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen) { tscDebugL("0x%"PRIx64" SQL: %s", pRequest->requestId, pRequest->sqlstr); - int32_t code = 0;//tsParseSql(pSql, true); + int32_t code = 0; if (qIsInsertSql(pRequest->sqlstr, sqlLen)) { -// qParseInsertSql(); + // todo add } else { - SQueryStmtInfo *pQueryInfo = qParseQuerySql(pRequest->sqlstr, sqlLen, pRequest->requestId, pRequest->msgBuf, ERROR_MSG_BUF_DEFAULT_SIZE); - assert(pQueryInfo != NULL); + int32_t type = 0; + void* output = NULL; + + code = qParseQuerySql(pRequest->sqlstr, sqlLen, pRequest->requestId, &type, &output, pRequest->msgBuf, ERROR_MSG_BUF_DEFAULT_SIZE); + if (type == TSDB_SQL_CREATE_USER || type == TSDB_SQL_SHOW) { + pRequest->type = type; + pRequest->body.param = output; + + SRequestMsgBody body = {0}; + buildRequestMsgFp[type](pRequest, &body); + + int64_t transporterId = 0; + sendMsgToServer(pTscObj->pTransporter, &pTscObj->pAppInfo->mgmtEp.epSet, &body, &transporterId); + + tsem_wait(&pRequest->body.rspSem); + destroyConnectMsg(&body); + } else { + assert(0); + } } if (code != TSDB_CODE_SUCCESS) { pRequest->code = code; -// tscAsyncResultOnError(pSql); -// taosReleaseRef(tscReqRef, p->self); - return NULL; + return pRequest; } -// executeQuery(pSql, pQueryInfo); -// doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen); - - tsem_wait(&pRequest->body.rspSem); return pRequest; } @@ -328,8 +339,8 @@ void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { pMsg->code = (*handleRequestRspFp[pRequest->type])(pRequest, pMsg->pCont, pMsg->contLen); } } else { - tscError("0x%" PRIx64 " SQL cmd:%s, code:%s rspLen:%d", pRequest->requestId, taosMsg[pMsg->msgType], - tstrerror(pMsg->code), pMsg->contLen); + tscError("0x%" PRIx64 " SQL cmd:%s, code:%s rspLen:%d, elapsed time:%"PRId64" ms", pRequest->requestId, taosMsg[pMsg->msgType], + tstrerror(pMsg->code), pMsg->contLen, pRequest->metric.rsp - pRequest->metric.start); } taosReleaseRef(tscReqRef, requestRefId); @@ -337,3 +348,30 @@ void processMsgFromServer(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { sem_post(&pRequest->body.rspSem); } + +TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port) { + tscDebug("try to connect to %s:%u by auth, user:%s db:%s", ip, port, user, db); + if (user == NULL) { + user = TSDB_DEFAULT_USER; + } + + if (auth == NULL) { + tscError("No auth info is given, failed to connect to server"); + return NULL; + } + + return taos_connect_internal(ip, user, NULL, auth, db, port); +} + +TAOS *taos_connect_l(const char *ip, int ipLen, const char *user, int userLen, const char *pass, int passLen, const char *db, int dbLen, uint16_t port) { + char ipStr[TSDB_EP_LEN] = {0}; + char dbStr[TSDB_DB_NAME_LEN] = {0}; + char userStr[TSDB_USER_LEN] = {0}; + char passStr[TSDB_PASSWORD_LEN] = {0}; + + strncpy(ipStr, ip, MIN(TSDB_EP_LEN - 1, ipLen)); + strncpy(userStr, user, MIN(TSDB_USER_LEN - 1, userLen)); + strncpy(passStr, pass, MIN(TSDB_PASSWORD_LEN - 1, passLen)); + strncpy(dbStr, db, MIN(TSDB_DB_NAME_LEN - 1, dbLen)); + return taos_connect(ipStr, userStr, passStr, dbStr, port); +} \ No newline at end of file diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index b039130433..0e71356e51 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -16,9 +16,6 @@ #define TSC_VAR_RELEASED 0 static int32_t sentinel = TSC_VAR_NOT_RELEASE; -static pthread_once_t tscinit = PTHREAD_ONCE_INIT; - -extern int32_t tscInitRes; int taos_options(TSDB_OPTION option, const void *arg, ...) { static int32_t lock = 0; @@ -36,11 +33,6 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) { return ret; } -int taos_init() { - pthread_once(&tscinit, taos_init_imp); - return tscInitRes; -} - // this function may be called by user or system, or by both simultaneously. void taos_cleanup(void) { tscDebug("start to cleanup client environment"); @@ -65,6 +57,21 @@ void taos_cleanup(void) { taosCloseLog(); } +TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) { + int32_t p = (port != 0)? port:tsServerPort; + + tscDebug("try to connect to %s:%u, user:%s db:%s", ip, p, user, db); + if (user == NULL) { + user = TSDB_DEFAULT_USER; + } + + if (pass == NULL) { + pass = TSDB_DEFAULT_PASS; + } + + return taos_connect_internal(ip, user, pass, NULL, db, p); +} + void taos_close(TAOS* taos) { if (taos == NULL) { return; @@ -76,12 +83,31 @@ void taos_close(TAOS* taos) { taosRemoveRef(tscConnRef, pTscObj->id); } -const char *taos_errstr(TAOS_RES *res) { +int taos_errno(TAOS_RES *tres) { + if (tres == NULL) { + return terrno; + } + return ((SRequestObj*) tres)->code; +} + +const char *taos_errstr(TAOS_RES *res) { + SRequestObj *pRequest = (SRequestObj *) res; + + if (pRequest == NULL) { + return (const char*) tstrerror(terrno); + } + + if (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR) { + return pRequest->msgBuf; + } else { + return (const char*)tstrerror(pRequest->code); + } } void taos_free_result(TAOS_RES *res) { - + SRequestObj* pRequest = (SRequestObj*) res; + destroyRequest(pRequest); } TAOS_RES *taos_query(TAOS *taos, const char *sql) { diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c index 606397dc78..d7d92ae3d1 100644 --- a/source/client/src/clientMsgHandler.c +++ b/source/client/src/clientMsgHandler.c @@ -3091,6 +3091,36 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, SQueryInfo* pQueryInfo) { #endif +int32_t buildConnectMsg(SRequestObj *pRequest, SRequestMsgBody* pMsgBody) { + pMsgBody->msgType = TSDB_MSG_TYPE_CONNECT; + pMsgBody->msgLen = sizeof(SConnectMsg); + pMsgBody->requestObjRefId = pRequest->self; + + SConnectMsg *pConnect = calloc(1, sizeof(SConnectMsg)); + if (pConnect == NULL) { + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; + return -1; + } + + // TODO refactor full_name + char *db; // ugly code to move the space + + STscObj *pObj = pRequest->pTscObj; + pthread_mutex_lock(&pObj->mutex); + db = strstr(pObj->db, TS_PATH_DELIMITER); + + db = (db == NULL) ? pObj->db : db + 1; + tstrncpy(pConnect->db, db, sizeof(pConnect->db)); + pthread_mutex_unlock(&pObj->mutex); + + pConnect->pid = htonl(appInfo.pid); + pConnect->startTime = htobe64(appInfo.startTime); + tstrncpy(pConnect->app, appInfo.appName, tListLen(pConnect->app)); + + pMsgBody->pData = pConnect; + return 0; +} + int processConnectRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) { STscObj *pTscObj = pRequest->pTscObj; @@ -3099,6 +3129,11 @@ int processConnectRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) { pConnect->connId = htonl(pConnect->connId); pConnect->clusterId = htonl(pConnect->clusterId); + assert(pConnect->epSet.numOfEps > 0); + for(int32_t i = 0; i < pConnect->epSet.numOfEps; ++i) { + pConnect->epSet.port[i] = htons(pConnect->epSet.port[i]); + } + // TODO refactor pthread_mutex_lock(&pTscObj->mutex); char temp[TSDB_TABLE_FNAME_LEN * 2] = {0}; @@ -3108,13 +3143,12 @@ int processConnectRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) { tstrncpy(pTscObj->db, temp, sizeof(pTscObj->db)); pthread_mutex_unlock(&pTscObj->mutex); - assert(pConnect->epSet.numOfEps > 0); if (!isEpsetEqual(&pTscObj->pAppInfo->mgmtEp.epSet, &pConnect->epSet)) { updateEpSet_s(&pTscObj->pAppInfo->mgmtEp, &pConnect->epSet); } for (int i = 0; i < pConnect->epSet.numOfEps; ++i) { - tscDebug("0x%" PRIx64 " epSet.fqdn[%d]: %s, connObj:0x%"PRIx64, pRequest->requestId, i, pConnect->epSet.fqdn[i], pTscObj->id); + tscDebug("0x%" PRIx64 " epSet.fqdn[%d]:%s port:%d, connObj:0x%"PRIx64, pRequest->requestId, i, pConnect->epSet.fqdn[i], pConnect->epSet.port[i], pTscObj->id); } pTscObj->connId = pConnect->connId; @@ -3124,10 +3158,14 @@ int processConnectRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) { atomic_add_fetch_64(&pTscObj->pAppInfo->numOfConns, 1); tscDebug("0x%" PRIx64 " clusterId:%d, totalConn:%"PRId64, pRequest->requestId, pConnect->clusterId, pTscObj->pAppInfo->numOfConns); - // createHbObj(pTscObj); + return 0; +} - // launch a timer to send heartbeat to maintain the connection and send status to mnode - // taosTmrReset(tscProcessActivityTimer, tsShellActivityTimer * 500, (void *)pTscObj->rid, tscTmr, &pTscObj->pTimer); +int32_t buildCreateUserMsg(SRequestObj *pRequest, SRequestMsgBody* pMsgBody) { + pMsgBody->msgType = TSDB_MSG_TYPE_CREATE_USER; + pMsgBody->msgLen = sizeof(SCreateUserMsg); + pMsgBody->requestObjRefId = pRequest->self; + pMsgBody->pData = pRequest->body.param; return 0; } @@ -3207,6 +3245,10 @@ void initMsgHandleFp() { tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_DATABASE] = tscProcessShowCreateRsp; #endif -// buildRequestMsgFp[TSDB_SQL_CONNECT] = tscBuildConnectMsg; + buildRequestMsgFp[TSDB_SQL_CONNECT] = buildConnectMsg; handleRequestRspFp[TSDB_SQL_CONNECT] = processConnectRsp; + + buildRequestMsgFp[TSDB_SQL_CREATE_USER] = buildCreateUserMsg; + + } \ No newline at end of file diff --git a/source/client/src/tscEnv.c b/source/client/src/tscEnv.c index 0e9be4af49..e378ebede4 100644 --- a/source/client/src/tscEnv.c +++ b/source/client/src/tscEnv.c @@ -35,6 +35,7 @@ int32_t tscReqRef = -1; int32_t tscConnRef = -1; void *tscQhandle = NULL; +static pthread_once_t tscinit = PTHREAD_ONCE_INIT; int32_t tsNumOfThreads = 1; volatile int32_t tscInitRes = 0; @@ -64,7 +65,7 @@ static void deregisterRequest(SRequestObj* pRequest) { SInstanceActivity* pActivity = &pTscObj->pAppInfo->summary; int32_t currentInst = atomic_sub_fetch_32(&pActivity->currentRequests, 1); - int32_t num = atomic_sub_fetch_32(&pTscObj->numOfReqs, 1); + int32_t num = atomic_sub_fetch_32(&pTscObj->numOfReqs, 1); tscDebug("0x%"PRIx64" free Request from connObj: 0x%"PRIx64", current:%d, app current:%d", pRequest->self, pTscObj->id, num, currentInst); taosReleaseRef(tscConnRef, pTscObj->id); @@ -251,6 +252,11 @@ void taos_init_imp(void) { tscDebug("client is initialized successfully"); } +int taos_init() { + pthread_once(&tscinit, taos_init_imp); + return tscInitRes; +} + int taos_options_imp(TSDB_OPTION option, const char *str) { SGlobalCfg *cfg = NULL; diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index 6f371dbd12..3e520e6ce6 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -14,6 +14,7 @@ */ #include +#include #include #include "tglobal.h" #pragma GCC diagnostic ignored "-Wwrite-strings" @@ -36,6 +37,14 @@ TEST(testCase, driverInit_Test) { TAOS* pConn = taos_connect("ubuntu", "root", "taosdata", NULL, 0); assert(pConn != NULL); - taos_query(pConn, "create user abc pass 'abc'"); + TAOS_RES* pRes = taos_query(pConn, "create user abc pass 'abc'"); + if (taos_errno(pRes) != TSDB_CODE_SUCCESS) { + printf("failed to create user, reason:%s\n", taos_errstr(pRes)); + } + + taos_free_result(pRes); + + pRes = taos_query(pConn, "show users"); + taos_close(pConn); } \ No newline at end of file diff --git a/source/libs/parser/inc/parserInt.h b/source/libs/parser/inc/parserInt.h index 47f655d446..16e5a3c629 100644 --- a/source/libs/parser/inc/parserInt.h +++ b/source/libs/parser/inc/parserInt.h @@ -53,6 +53,15 @@ void clearAllTableMetaInfo(SQueryStmtInfo* pQueryInfo, bool removeMeta, uint64_t */ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pSqlInfo, SQueryStmtInfo* pQueryInfo, int64_t id, char* msg, int32_t msgLen); +/** + * validate the ddl ast, and convert the ast to the corresponding message format + * @param pSqlInfo + * @param output + * @param type + * @return + */ +int32_t qParserValidateDdlSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* type, char* msgBuf, int32_t msgBufLen); + /** * Evaluate the numeric and timestamp arithmetic expression in the WHERE clause. * @param pNode diff --git a/source/libs/parser/inc/parserUtil.h b/source/libs/parser/inc/parserUtil.h index 6c95c4327b..bd1d5ac633 100644 --- a/source/libs/parser/inc/parserUtil.h +++ b/source/libs/parser/inc/parserUtil.h @@ -45,6 +45,8 @@ int32_t getNumOfFields(SFieldInfo* pFieldInfo); SInternalField* getInternalField(SFieldInfo* pFieldInfo, int32_t index); int32_t parserValidateIdToken(SToken* pToken); +int32_t parserValidatePassword(SToken* pToken, SMsgBuf* pMsgBuf); + int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg); int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr); @@ -63,6 +65,8 @@ int32_t getExprFunctionId(SExprInfo *pExprInfo); STableMeta* tableMetaDup(const STableMeta* pTableMeta); +bool isDdlSql(SSqlInfo* pSqlInfo); + #ifdef __cplusplus } #endif diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c index 7b6c423fb6..26ca3c52e4 100644 --- a/source/libs/parser/src/astValidate.c +++ b/source/libs/parser/src/astValidate.c @@ -13,7 +13,6 @@ * along with this program. If not, see . */ -#include #include "astGenerator.h" #include "function.h" #include "parserInt.h" @@ -23,6 +22,7 @@ #include "tglobal.h" #include "tmsgtype.h" #include "ttime.h" +#include "astToMsg.h" #define TSQL_TBNAME_L "tbname" #define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0" @@ -3636,11 +3636,14 @@ int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, SMsgBuf* pMsgBuf) } int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQueryStmtInfo* pQueryInfo, int64_t id, char* msgBuf, int32_t msgBufLen) { - //1. if it is a query, get the meta info and continue. assert(pCatalog != NULL && pInfo != NULL); int32_t code = 0; -#if 0 + + SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; + SMsgBuf *pMsgBuf = &m; + switch (pInfo->type) { +#if 0 case TSDB_SQL_DROP_TABLE: case TSDB_SQL_DROP_USER: case TSDB_SQL_DROP_ACCT: @@ -3651,14 +3654,14 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer SToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0); if ((pInfo->type != TSDB_SQL_DROP_DNODE) && (parserValidateIdToken(pzName) != TSDB_CODE_SUCCESS)) { - return setInvalidOperatorMsg(pMsgBuf, msg2); + return buildInvalidOperationMsg(pMsgBuf, msg2); } if (pInfo->type == TSDB_SQL_DROP_DB) { assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1); code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName); if (code != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg2); + return buildInvalidOperationMsg(pMsgBuf, msg2); } } else if (pInfo->type == TSDB_SQL_DROP_TABLE) { @@ -3675,7 +3678,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer strncpy(pCmd->payload, pzName->z, pzName->n); } else { // drop user/account if (pzName->n >= TSDB_USER_LEN) { - return setInvalidOperatorMsg(pMsgBuf, msg3); + return buildInvalidOperationMsg(pMsgBuf, msg3); } strncpy(pCmd->payload, pzName->z, pzName->n); @@ -3689,12 +3692,12 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg); + return buildInvalidOperationMsg(pMsgBuf, msg); } int32_t ret = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pToken); if (ret != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg); + return buildInvalidOperationMsg(pMsgBuf, msg); } break; @@ -3729,19 +3732,19 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer SCreateDbInfo* pCreateDB = &(pInfo->pMiscInfo->dbOpt); if (pCreateDB->dbname.n >= TSDB_DB_NAME_LEN) { - return setInvalidOperatorMsg(pMsgBuf, msg2); + return buildInvalidOperationMsg(pMsgBuf, msg2); } char buf[TSDB_DB_NAME_LEN] = {0}; SToken token = taosTokenDup(&pCreateDB->dbname, buf, tListLen(buf)); if (tscValidateName(&token) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } int32_t ret = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), &token); if (ret != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg2); + return buildInvalidOperationMsg(pMsgBuf, msg2); } if (parseCreateDBOptions(pCmd, pCreateDB) != TSDB_CODE_SUCCESS) { @@ -3755,7 +3758,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer const char* msg = "invalid host name (ip address)"; if (taosArrayGetSize(pInfo->pMiscInfo->a) > 1) { - return setInvalidOperatorMsg(pMsgBuf, msg); + return buildInvalidOperationMsg(pMsgBuf, msg); } SToken* id = taosArrayGet(pInfo->pMiscInfo->a, 0); @@ -3779,11 +3782,11 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer } if (pName->n >= TSDB_USER_LEN) { - return setInvalidOperatorMsg(pMsgBuf, msg3); + return buildInvalidOperationMsg(pMsgBuf, msg3); } if (tscValidateName(pName) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg2); + return buildInvalidOperationMsg(pMsgBuf, msg2); } SCreateAcctInfo* pAcctOpt = &pInfo->pMiscInfo->acctOpt; @@ -3793,7 +3796,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer } else if (strncmp(pAcctOpt->stat.z, "all", 3) == 0 && pAcctOpt->stat.n == 3) { } else if (strncmp(pAcctOpt->stat.z, "no", 2) == 0 && pAcctOpt->stat.n == 2) { } else { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } } @@ -3805,7 +3808,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } // additional msg has been attached already code = tscSetTableFullName(&pTableMetaInfo->name, pToken, pSql); @@ -3821,7 +3824,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } code = tscSetTableFullName(&pTableMetaInfo->name, pToken, pSql); @@ -3836,11 +3839,11 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } if (pToken->n > TSDB_DB_NAME_LEN) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } return tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pToken); } @@ -3853,7 +3856,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer /* validate the parameter names and options */ if (validateDNodeConfig(pMiscInfo) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg2); + return buildInvalidOperationMsg(pMsgBuf, msg2); } char* pMsg = pCmd->payload; @@ -3867,7 +3870,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer strncpy(pCfg->ep, t0->z, t0->n); if (validateEp(pCfg->ep) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg3); + return buildInvalidOperationMsg(pMsgBuf, msg3); } strncpy(pCfg->config, t1->z, t1->n); @@ -3882,65 +3885,13 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer break; } - case TSDB_SQL_CREATE_USER: - case TSDB_SQL_ALTER_USER: { - const char* msg2 = "invalid user/account name"; - const char* msg3 = "name too long"; - const char* msg5 = "invalid user rights"; - const char* msg7 = "not support options"; - - pCmd->command = pInfo->type; - - SUserInfo* pUser = &pInfo->pMiscInfo->user; - SToken* pName = &pUser->user; - SToken* pPwd = &pUser->passwd; - - if (pName->n >= TSDB_USER_LEN) { - return setInvalidOperatorMsg(pMsgBuf, msg3); - } - - if (tscValidateName(pName) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg2); - } - - if (pCmd->command == TSDB_SQL_CREATE_USER) { - if (handlePassword(pCmd, pPwd) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } else { - if (pUser->type == TSDB_ALTER_USER_PASSWD) { - if (handlePassword(pCmd, pPwd) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } else if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) { - assert(pPwd->type == TSDB_DATA_TYPE_NULL); - - SToken* pPrivilege = &pUser->privilege; - - if (strncasecmp(pPrivilege->z, "super", 5) == 0 && pPrivilege->n == 5) { - pCmd->count = 1; - } else if (strncasecmp(pPrivilege->z, "read", 4) == 0 && pPrivilege->n == 4) { - pCmd->count = 2; - } else if (strncasecmp(pPrivilege->z, "write", 5) == 0 && pPrivilege->n == 5) { - pCmd->count = 3; - } else { - return setInvalidOperatorMsg(pMsgBuf, msg5); - } - } else { - return setInvalidOperatorMsg(pMsgBuf, msg7); - } - } - - break; - } - case TSDB_SQL_CFG_LOCAL: { SMiscInfo *pMiscInfo = pInfo->pMiscInfo; const char *msg = "invalid configure options or values"; // validate the parameter names and options if (validateLocalConfig(pMiscInfo) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg); + return buildInvalidOperationMsg(pMsgBuf, msg); } int32_t numOfToken = (int32_t) taosArrayGetSize(pMiscInfo->a); @@ -3995,7 +3946,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer tscTrace("0x%"PRIx64" start to parse the %dth subclause, total:%"PRIzu, pSql->self, i, size); if (size > 1 && pSqlNode->from && pSqlNode->from->type == SQL_FROM_NODE_SUBQUERY) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } // normalizeSqlNode(pSqlNode); // normalize the column name in each function @@ -4061,21 +4012,22 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1); code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName); if (code != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg1); + return buildInvalidOperationMsg(pMsgBuf, msg1); } break; } case TSDB_SQL_COMPACT_VNODE:{ const char* msg = "invalid compact"; if (setCompactVnodeInfo(pSql, pInfo) != TSDB_CODE_SUCCESS) { - return setInvalidOperatorMsg(pMsgBuf, msg); + return buildInvalidOperationMsg(pMsgBuf, msg); } break; } + #endif default: - return setInvalidOperatorMsg(pMsgBuf, "not support sql expression"); + return buildInvalidOperationMsg(pMsgBuf, "not support sql expression"); } -#endif + SMetaReq req = {0}; SMetaData data = {0}; @@ -4116,3 +4068,66 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer return code; } + +int32_t qParserValidateDdlSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* type, char* msgBuf, int32_t msgBufLen) { + int32_t code = 0; + + SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; + SMsgBuf *pMsgBuf = &m; + + *type = pInfo->type; + + switch (pInfo->type) { + case TSDB_SQL_CREATE_USER: + case TSDB_SQL_ALTER_USER: { + const char* msg1 = "not support options"; + const char* msg2 = "invalid user/account name"; + const char* msg3 = "name too long"; + const char* msg4 = "invalid user rights"; + + SUserInfo* pUser = &pInfo->pMiscInfo->user; + SToken* pName = &pUser->user; + SToken* pPwd = &pUser->passwd; + + if (pName->n >= TSDB_USER_LEN) { + return buildInvalidOperationMsg(pMsgBuf, msg3); + } + + if (parserValidateIdToken(pName) != TSDB_CODE_SUCCESS) { + return buildInvalidOperationMsg(pMsgBuf, msg2); + } + + if (pInfo->type == TSDB_SQL_CREATE_USER) { + if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + } else { + if (pUser->type == TSDB_ALTER_USER_PASSWD) { + if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + } else if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) { + assert(pPwd->type == TSDB_DATA_TYPE_NULL); + + SToken* pPrivilege = &pUser->privilege; + if (strncasecmp(pPrivilege->z, "super", 5) == 0 && pPrivilege->n == 5) { + // pCmd->count = 1; + } else if (strncasecmp(pPrivilege->z, "normal", 4) == 0 && pPrivilege->n == 4) { + // pCmd->count = 2; + } else { + return buildInvalidOperationMsg(pMsgBuf, msg4); + } + } else { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + } + + *output = buildUserManipulationMsg(pInfo, id, msgBuf, msgBufLen); + break; + } + default: + break; + } + + return 0; +} diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index 42d6fc1c5e..78ffa7a98e 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -31,27 +31,35 @@ bool qIsInsertSql(const char* pStr, size_t length) { } while (1); } -SQueryStmtInfo* qParseQuerySql(const char* pStr, size_t length, int64_t id, char* msg, int32_t msgLen) { +int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t *type, void** pOutput, char* msg, int32_t msgLen) { SQueryStmtInfo* pQueryInfo = calloc(1, sizeof(SQueryStmtInfo)); if (pQueryInfo == NULL) { terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; // set correct error code. - return NULL; + return terrno; } SSqlInfo info = doGenerateAST(pStr); if (!info.valid) { strncpy(msg, info.msg, msgLen); terrno = TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - return NULL; + return terrno; } - struct SCatalog* pCatalog = getCatalogHandle(NULL); - int32_t code = qParserValidateSqlNode(pCatalog, &info, pQueryInfo, id, msg, msgLen); - if (code == TSDB_CODE_SUCCESS) { - return pQueryInfo; + if (isDdlSql(&info)) { + int32_t code = qParserValidateDdlSqlNode(&info, id, pOutput, type, msg, msgLen); + if (code == TSDB_CODE_SUCCESS) { + // do nothing + } + } else { + struct SCatalog* pCatalog = getCatalogHandle(NULL); + + int32_t code = qParserValidateSqlNode(pCatalog, &info, pQueryInfo, id, msg, msgLen); + if (code == TSDB_CODE_SUCCESS) { + *pOutput = pQueryInfo; + } } - return NULL; + return TSDB_CODE_SUCCESS; } int32_t qParseInsertSql(SParseContext* pContext, SInsertStmtInfo** pInfo) { diff --git a/source/libs/parser/src/parserUtil.c b/source/libs/parser/src/parserUtil.c index 7b3239c0dd..b9d31b1985 100644 --- a/source/libs/parser/src/parserUtil.c +++ b/source/libs/parser/src/parserUtil.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ #include "parserUtil.h" +#include #include "taosmsg.h" #include "parser.h" @@ -97,12 +98,35 @@ int32_t parserValidateIdToken(SToken* pToken) { return TSDB_CODE_SUCCESS; } +int32_t parserValidatePassword(SToken* pToken, SMsgBuf* pMsgBuf) { + const char* msg1 = "password can not be empty"; + const char* msg2 = "name or password too long"; + const char* msg3 = "password needs single quote marks enclosed"; + + if (pToken->type != TK_STRING) { + return buildInvalidOperationMsg(pMsgBuf, msg3); + } + + strdequote(pToken->z); + + pToken->n = (uint32_t)strtrim(pToken->z); // trim space before and after passwords + if (pToken->n <= 0) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + + if (pToken->n >= TSDB_USET_PASSWORD_LEN) { + return buildInvalidOperationMsg(pMsgBuf, msg2); + } + + return TSDB_CODE_SUCCESS; +} + int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) { strncpy(pBuf->buf, msg, pBuf->len); return TSDB_CODE_TSC_INVALID_OPERATION; } -int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) { +int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) { const char* msgFormat1 = "syntax error near \'%s\'"; const char* msgFormat2 = "syntax error near \'%s\' (%s)"; const char* msgFormat3 = "%s"; @@ -584,21 +608,6 @@ int32_t getNumOfFields(SFieldInfo* pFieldInfo) { return pFieldInfo->numOfOutput; } -int32_t getFirstInvisibleFieldPos(SQueryStmtInfo* pQueryInfo) { - if (pQueryInfo->fieldsInfo.numOfOutput <= 0 || pQueryInfo->fieldsInfo.internalField == NULL) { - return 0; - } - - for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { - SInternalField* pField = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i); - if (!pField->visible) { - return i; - } - } - - return pQueryInfo->fieldsInfo.numOfOutput; -} - SInternalField* appendFieldInfo(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) { assert(pFieldInfo != NULL); pFieldInfo->numOfOutput++; @@ -1623,6 +1632,10 @@ uint32_t convertRelationalOperator(SToken *pToken) { } } +bool isDdlSql(SSqlInfo* pSqlInfo) { + return (pSqlInfo->type != TSDB_SQL_SELECT); +} + #if 0 int32_t tscCreateQueryFromQueryInfo(SQueryStmtInfo* pQueryInfo, SQueryAttr* pQueryAttr, void* addr) { memset(pQueryAttr, 0, sizeof(SQueryAttr)); diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp index 2193a44604..07637d27cf 100644 --- a/source/libs/parser/test/parserTests.cpp +++ b/source/libs/parser/test/parserTests.cpp @@ -29,6 +29,7 @@ #include "taos.h" #include "tdef.h" #include "tvariant.h" +#include "parserUtil.h" namespace { void setSchema(SSchema* p, int32_t type, int32_t bytes, const char* name, int32_t colId) { @@ -700,5 +701,49 @@ TEST(testCase, function_Test6) { destroyQueryInfo(pQueryInfo); qParserClearupMetaRequestInfo(&req); + destroySqlInfo(&info1); +} + +TEST(testCase, show_user_Test) { + char msg[128] = {0}; + SMsgBuf buf; + buf.len = 128; + buf.buf = msg; + + char sql1[] = "show users"; + SSqlInfo info1 = doGenerateAST(sql1); + ASSERT_EQ(info1.valid, true); + + // convert the show command to be the select query + // select name, privilege, create_time, account from information_schema.users; + + + SQueryStmtInfo* pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); + +// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_NE(ret, 0); +} + +TEST(testCase, create_user_Test) { + char msg[128] = {0}; + SMsgBuf buf; + buf.len = 128; + buf.buf = msg; + + char sql[] = {"create user abc pass 'abc'"}; + + SSqlInfo info1 = doGenerateAST(sql); + ASSERT_EQ(info1.valid, true); + + ASSERT_EQ(isDdlSql(&info1), true); + + void* output = NULL; + int32_t type = 0; + + int32_t code = qParserValidateDdlSqlNode(&info1, 1, &output, &type, msg, buf.len); + ASSERT_EQ(code, 0); + destroySqlInfo(&info1); } \ No newline at end of file From cfce13407f5e4b290f2a21a201a52c112e8167ab Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 16 Dec 2021 15:45:09 +0800 Subject: [PATCH 3/4] [td-11818] implementate the taos_fetch_row . --- include/common/taosmsg.h | 2 +- include/libs/parser/parser.h | 2 +- source/client/inc/clientInt.h | 17 ++++- source/client/src/clientImpl.c | 22 +++++- source/client/src/clientMain.c | 14 ++++ source/client/src/clientMsgHandler.c | 72 ++++++++++++++++++- source/client/test/clientTests.cpp | 16 +++-- source/dnode/mnode/impl/src/mndUser.c | 2 +- source/libs/parser/inc/parserInt.h | 2 +- source/libs/parser/inc/parserUtil.h | 2 +- source/libs/parser/src/astValidate.c | 95 ++++++++++++++++++++++++- source/libs/parser/src/parser.c | 6 +- source/libs/parser/src/parserUtil.c | 7 +- source/libs/parser/test/parserTests.cpp | 20 +++--- 14 files changed, 242 insertions(+), 37 deletions(-) diff --git a/include/common/taosmsg.h b/include/common/taosmsg.h index 1d44255f6d..b76f82d0a2 100644 --- a/include/common/taosmsg.h +++ b/include/common/taosmsg.h @@ -804,7 +804,7 @@ typedef struct { } SVgroupsMsg, SVgroupsInfo; typedef struct { - char tbFname[TSDB_TABLE_FNAME_LEN]; // table id + char tbFname[TSDB_TABLE_FNAME_LEN]; // table full name char stbFname[TSDB_TABLE_FNAME_LEN]; int32_t numOfTags; int32_t numOfColumns; diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index c766bd99b2..32d0d03d80 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -151,7 +151,7 @@ typedef struct SParseContext { * @param msg extended error message if exists. * @return error code */ -int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t* type, void** pOutput, char* msg, int32_t msgLen); +int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t* type, void** pOutput, int32_t* outputLen, char* msg, int32_t msgLen); typedef enum { PAYLOAD_TYPE_KV = 0, diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 64dce1e5b1..b7cdc5d3d3 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -20,14 +20,15 @@ extern "C" { #endif +#include #include "taos.h" #include "taosmsg.h" +#include "tdef.h" +#include "tep.h" #include "thash.h" #include "tlist.h" -#include "trpc.h" -#include "tdef.h" #include "tmsgtype.h" -#include "tep.h" +#include "trpc.h" typedef struct SQueryExecMetric { int64_t start; // start timestamp @@ -86,10 +87,18 @@ typedef struct STscObj { SAppInstInfo *pAppInfo; } STscObj; +typedef struct SClientResultInfo { + SSDataBlock *pData; + TAOS_FIELD *resultFields; + int32_t current; +} SClientResultInfo; + typedef struct SReqBody { tsem_t rspSem; // not used now void* fp; void* param; + int32_t paramLen; + SClientResultInfo* pResInfo; } SRequestBody; #define ERROR_MSG_BUF_DEFAULT_SIZE 512 @@ -142,6 +151,8 @@ void initMsgHandleFp(); TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, const char *auth, const char *db, uint16_t port); TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen); +void* doFetchRow(SRequestObj* pRequest); + #ifdef __cplusplus } #endif diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index a0b7d5e9a7..de7fc78c4a 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -149,11 +149,12 @@ TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen) { } else { int32_t type = 0; void* output = NULL; - - code = qParseQuerySql(pRequest->sqlstr, sqlLen, pRequest->requestId, &type, &output, pRequest->msgBuf, ERROR_MSG_BUF_DEFAULT_SIZE); + int32_t outputLen = 0; + code = qParseQuerySql(pRequest->sqlstr, sqlLen, pRequest->requestId, &type, &output, &outputLen, pRequest->msgBuf, ERROR_MSG_BUF_DEFAULT_SIZE); if (type == TSDB_SQL_CREATE_USER || type == TSDB_SQL_SHOW) { pRequest->type = type; pRequest->body.param = output; + pRequest->body.paramLen = outputLen; SRequestMsgBody body = {0}; buildRequestMsgFp[type](pRequest, &body); @@ -374,4 +375,21 @@ TAOS *taos_connect_l(const char *ip, int ipLen, const char *user, int userLen, c strncpy(passStr, pass, MIN(TSDB_PASSWORD_LEN - 1, passLen)); strncpy(dbStr, db, MIN(TSDB_DB_NAME_LEN - 1, dbLen)); return taos_connect(ipStr, userStr, passStr, dbStr, port); +} + +void* doFetchRow(SRequestObj* pRequest) { + assert(pRequest != NULL); + SClientResultInfo* pResultInfo = pRequest->body.pResInfo; + + if (pResultInfo == NULL || pResultInfo->current >= pResultInfo->pData->info.rows) { + if (pResultInfo == NULL) { + pRequest->body.pResInfo = calloc(1, sizeof(SClientResultInfo)); +// pRequest->body.pResInfo. + } + // current data set are exhausted, fetch more result from node +// if (pRes->row >= pRes->numOfRows && needToFetchNewBlock(pSql)) { +// taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj); +// tsem_wait(&pSql->rspSem); +// } + } } \ No newline at end of file diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 0e71356e51..5a1f55e573 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -117,3 +117,17 @@ TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taos_query_l(taos, sql, strlen(sql)); } + +TAOS_ROW taos_fetch_row(TAOS_RES *pRes) { + if (pRes == NULL) { + return NULL; + } + + SRequestObj *pRequest = (SRequestObj *) pRes; + if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || + pRequest->type == TSDB_SQL_INSERT) { + return NULL; + } + + return doFetchRow(pRequest); +} diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c index d7d92ae3d1..6501aff21c 100644 --- a/source/client/src/clientMsgHandler.c +++ b/source/client/src/clientMsgHandler.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include #include "clientInt.h" #include "clientLog.h" #include "os.h" @@ -3165,7 +3166,74 @@ int32_t buildCreateUserMsg(SRequestObj *pRequest, SRequestMsgBody* pMsgBody) { pMsgBody->msgType = TSDB_MSG_TYPE_CREATE_USER; pMsgBody->msgLen = sizeof(SCreateUserMsg); pMsgBody->requestObjRefId = pRequest->self; - pMsgBody->pData = pRequest->body.param; + pMsgBody->pData = pRequest->body.param; + return 0; +} + +int32_t buildShowMsg(SRequestObj* pRequest, SRequestMsgBody* pMsgBody) { + pMsgBody->msgType = TSDB_MSG_TYPE_SHOW; + pMsgBody->msgLen = pRequest->body.paramLen; + pMsgBody->requestObjRefId = pRequest->self; + pMsgBody->pData = pRequest->body.param; +} + +STableMeta* createTableMetaFromMsg(STableMetaMsg* pTableMetaMsg) { + assert(pTableMetaMsg != NULL && pTableMetaMsg->numOfColumns >= 2); + + size_t schemaSize = (pTableMetaMsg->numOfColumns + pTableMetaMsg->numOfTags) * sizeof(SSchema); + STableMeta* pTableMeta = calloc(1, sizeof(STableMeta) + schemaSize); + + pTableMeta->tableType = pTableMetaMsg->tableType; + pTableMeta->vgId = pTableMetaMsg->vgroup.vgId; + pTableMeta->suid = pTableMetaMsg->suid; + pTableMeta->uid = pTableMetaMsg->tuid; + + pTableMeta->tableInfo = (STableComInfo) { + .numOfTags = pTableMetaMsg->numOfTags, + .precision = pTableMetaMsg->precision, + .numOfColumns = pTableMetaMsg->numOfColumns, + }; + + pTableMeta->sversion = pTableMetaMsg->sversion; + pTableMeta->tversion = pTableMetaMsg->tversion; + + memcpy(pTableMeta->schema, pTableMetaMsg->pSchema, schemaSize); + + int32_t numOfTotalCols = pTableMeta->tableInfo.numOfColumns; + for(int32_t i = 0; i < numOfTotalCols; ++i) { + pTableMeta->tableInfo.rowSize += pTableMeta->schema[i].bytes; + } + + return pTableMeta; +} + +int32_t processShowRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) { + SShowRsp* pShow = (SShowRsp *)pMsg; + pShow->showId = htonl(pShow->showId); + + STableMetaMsg *pMetaMsg = &(pShow->tableMeta); + pMetaMsg->numOfColumns = htonl(pMetaMsg->numOfColumns); + + SSchema* pSchema = pMetaMsg->pSchema; + pMetaMsg->tuid = htobe64(pMetaMsg->tuid); + for (int i = 0; i < pMetaMsg->numOfColumns; ++i) { + pSchema->bytes = htons(pSchema->bytes); + pSchema++; + } + + STableMeta* pTableMeta = createTableMetaFromMsg(pMetaMsg); + SSchema *pTableSchema = pTableMeta->schema; + + TAOS_FIELD* pFields = calloc(1, pTableMeta->tableInfo.numOfColumns); + for (int16_t i = 0; i < pTableMeta->tableInfo.numOfColumns; ++i, ++pSchema) { + tstrncpy(pFields[i].name, pTableSchema[i].name, tListLen(pFields[i].name)); + pFields[i].type = pTableSchema[i].type; + pFields[i].bytes = pTableSchema[i].bytes; + } + +// pRequest->body.resultFields = pFields; +// pRequest->body.numOfFields = pTableMeta->tableInfo.numOfColumns; + return 0; } @@ -3250,5 +3318,7 @@ void initMsgHandleFp() { buildRequestMsgFp[TSDB_SQL_CREATE_USER] = buildCreateUserMsg; + buildRequestMsgFp[TSDB_SQL_SHOW] = buildShowMsg; + handleRequestRspFp[TSDB_SQL_SHOW] = processShowRsp; } \ No newline at end of file diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index 3e520e6ce6..62d2cb5b18 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -37,14 +37,16 @@ TEST(testCase, driverInit_Test) { TAOS* pConn = taos_connect("ubuntu", "root", "taosdata", NULL, 0); assert(pConn != NULL); - TAOS_RES* pRes = taos_query(pConn, "create user abc pass 'abc'"); - if (taos_errno(pRes) != TSDB_CODE_SUCCESS) { - printf("failed to create user, reason:%s\n", taos_errstr(pRes)); - } +// TAOS_RES* pRes = taos_query(pConn, "create user abc pass 'abc'"); +// if (taos_errno(pRes) != TSDB_CODE_SUCCESS) { +// printf("failed to create user, reason:%s\n", taos_errstr(pRes)); +// } +// +// taos_free_result(pRes); - taos_free_result(pRes); - - pRes = taos_query(pConn, "show users"); + TAOS_RES* pRes = taos_query(pConn, "show users"); + TAOS_ROW pRow = taos_fetch_row(pRes); + assert(pRow != NULL); taos_close(pConn); } \ No newline at end of file diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index 2111047219..419936f14c 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -471,7 +471,7 @@ static int32_t mndGetUserMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *p pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; - pMeta->numOfColumns = htons(cols); + pMeta->numOfColumns = htonl(cols); pShow->numOfColumns = cols; pShow->offset[0] = 0; diff --git a/source/libs/parser/inc/parserInt.h b/source/libs/parser/inc/parserInt.h index 16e5a3c629..8e8dc27c4f 100644 --- a/source/libs/parser/inc/parserInt.h +++ b/source/libs/parser/inc/parserInt.h @@ -60,7 +60,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pSqlInfo, SQ * @param type * @return */ -int32_t qParserValidateDdlSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* type, char* msgBuf, int32_t msgBufLen); +int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* outputLen, int32_t* type, char* msgBuf, int32_t msgBufLen); /** * Evaluate the numeric and timestamp arithmetic expression in the WHERE clause. diff --git a/source/libs/parser/inc/parserUtil.h b/source/libs/parser/inc/parserUtil.h index bd1d5ac633..b402621903 100644 --- a/source/libs/parser/inc/parserUtil.h +++ b/source/libs/parser/inc/parserUtil.h @@ -65,7 +65,7 @@ int32_t getExprFunctionId(SExprInfo *pExprInfo); STableMeta* tableMetaDup(const STableMeta* pTableMeta); -bool isDdlSql(SSqlInfo* pSqlInfo); +bool isDclSqlStatement(SSqlInfo* pSqlInfo); #ifdef __cplusplus } diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c index 26ca3c52e4..300dd53df3 100644 --- a/source/libs/parser/src/astValidate.c +++ b/source/libs/parser/src/astValidate.c @@ -4069,7 +4069,93 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer return code; } -int32_t qParserValidateDdlSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* type, char* msgBuf, int32_t msgBufLen) { +// todo remove it +static int32_t setShowInfo(struct SSqlInfo* pInfo, void** output, int32_t* msgLen, SMsgBuf* pMsgBuf) { + const char* msg1 = "invalid name"; + const char* msg2 = "wildcard string should be less than %d characters"; + const char* msg3 = "database name too long"; + const char* msg4 = "pattern is invalid"; + const char* msg5 = "database name is empty"; + const char* msg6 = "pattern string is empty"; + + /* + * database prefix in pInfo->pMiscInfo->a[0] + * wildcard in like clause in pInfo->pMiscInfo->a[1] + */ + SShowInfo* pShowInfo = &pInfo->pMiscInfo->showOpt; + int16_t showType = pShowInfo->showType; + if (showType == TSDB_MGMT_TABLE_TABLE || showType == TSDB_MGMT_TABLE_VGROUP) { + SToken* pDbPrefixToken = &pShowInfo->prefix; + if (pDbPrefixToken->type != 0) { + if (pDbPrefixToken->n >= TSDB_DB_NAME_LEN) { // db name is too long + return buildInvalidOperationMsg(pMsgBuf, msg3); + } + + if (pDbPrefixToken->n <= 0) { + return buildInvalidOperationMsg(pMsgBuf, msg5); + } + + if (parserValidateIdToken(pDbPrefixToken) != TSDB_CODE_SUCCESS) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + + // int32_t ret = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pRequest->pTsc), pDbPrefixToken); + // if (ret != TSDB_CODE_SUCCESS) { + // return buildInvalidOperationMsg(pMsgBuf, msg1); + // } + } + + // show table/stable like 'xxxx', set the like pattern for show tables + SToken* pPattern = &pShowInfo->pattern; + if (pPattern->type != 0) { + if (pPattern->type == TK_ID && pPattern->z[0] == TS_ESCAPE_CHAR) { + return buildInvalidOperationMsg(pMsgBuf, msg4); + } + + pPattern->n = strdequote(pPattern->z); + if (pPattern->n <= 0) { + return buildInvalidOperationMsg(pMsgBuf, msg6); + } + + if (pPattern->n > tsMaxWildCardsLen) { + char tmp[64] = {0}; + sprintf(tmp, msg2, tsMaxWildCardsLen); + return buildInvalidOperationMsg(pMsgBuf, tmp); + } + } + } else if (showType == TSDB_MGMT_TABLE_VNODES) { + if (pShowInfo->prefix.type == 0) { + return buildInvalidOperationMsg(pMsgBuf, "No specified dnode ep"); + } + + if (pShowInfo->prefix.type == TK_STRING) { + pShowInfo->prefix.n = strdequote(pShowInfo->prefix.z); + } + } + + SShowMsg* pShowMsg = calloc(1, sizeof(SShowMsg)); + pShowMsg->type = pShowInfo->showType; + + if (pShowInfo->showType != TSDB_MGMT_TABLE_VNODES) { + SToken* pPattern = &pShowInfo->pattern; + if (pPattern->type > 0) { // only show tables support wildcard query + strncpy(pShowMsg->payload, pPattern->z, pPattern->n); + pShowMsg->payloadLen = htons(pPattern->n); + } + } else { + SToken* pEpAddr = &pShowInfo->prefix; + assert(pEpAddr->n > 0 && pEpAddr->type > 0); + + strncpy(pShowMsg->payload, pEpAddr->z, pEpAddr->n); + pShowMsg->payloadLen = htons(pEpAddr->n); + } + + *output = pShowMsg; + *msgLen = sizeof(SShowMsg) + htons(pShowMsg->payloadLen); + return TSDB_CODE_SUCCESS; +} + +int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* outputLen, int32_t* type, char* msgBuf, int32_t msgBufLen) { int32_t code = 0; SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; @@ -4125,9 +4211,14 @@ int32_t qParserValidateDdlSqlNode(SSqlInfo* pInfo, int64_t id, void** output, in *output = buildUserManipulationMsg(pInfo, id, msgBuf, msgBufLen); break; } + + case TSDB_SQL_SHOW: { + code = setShowInfo(pInfo, output, outputLen, pMsgBuf); + break; + } default: break; } - return 0; + return code; } diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index 78ffa7a98e..4d08ddba96 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -31,7 +31,7 @@ bool qIsInsertSql(const char* pStr, size_t length) { } while (1); } -int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t *type, void** pOutput, char* msg, int32_t msgLen) { +int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t *type, void** pOutput, int32_t* outputLen, char* msg, int32_t msgLen) { SQueryStmtInfo* pQueryInfo = calloc(1, sizeof(SQueryStmtInfo)); if (pQueryInfo == NULL) { terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; // set correct error code. @@ -45,8 +45,8 @@ int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t *typ return terrno; } - if (isDdlSql(&info)) { - int32_t code = qParserValidateDdlSqlNode(&info, id, pOutput, type, msg, msgLen); + if (isDclSqlStatement(&info)) { + int32_t code = qParserValidateDclSqlNode(&info, id, pOutput, outputLen, type, msg, msgLen); if (code == TSDB_CODE_SUCCESS) { // do nothing } diff --git a/source/libs/parser/src/parserUtil.c b/source/libs/parser/src/parserUtil.c index b9d31b1985..28c3bf20ef 100644 --- a/source/libs/parser/src/parserUtil.c +++ b/source/libs/parser/src/parserUtil.c @@ -12,8 +12,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include "parserUtil.h" -#include + #include "taosmsg.h" #include "parser.h" @@ -23,6 +22,8 @@ #include "thash.h" #include "tbuffer.h" #include "parserInt.h" +#include "parserUtil.h" +#include "tmsgtype.h" #include "queryInfoUtil.h" #include "function.h" @@ -1632,7 +1633,7 @@ uint32_t convertRelationalOperator(SToken *pToken) { } } -bool isDdlSql(SSqlInfo* pSqlInfo) { +bool isDclSqlStatement(SSqlInfo* pSqlInfo) { return (pSqlInfo->type != TSDB_SQL_SELECT); } diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp index 07637d27cf..3a929c32f2 100644 --- a/source/libs/parser/test/parserTests.cpp +++ b/source/libs/parser/test/parserTests.cpp @@ -714,16 +714,14 @@ TEST(testCase, show_user_Test) { SSqlInfo info1 = doGenerateAST(sql1); ASSERT_EQ(info1.valid, true); + void* output = NULL; + int32_t type = 0; + int32_t len = 0; + int32_t code = qParserValidateDclSqlNode(&info1, 1, &output, &len, &type, msg, buf.len); + ASSERT_EQ(code, 0); + // convert the show command to be the select query // select name, privilege, create_time, account from information_schema.users; - - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); -// setTableMetaInfo(pQueryInfo, &req); - -// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); -// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); -// ASSERT_NE(ret, 0); } TEST(testCase, create_user_Test) { @@ -737,12 +735,12 @@ TEST(testCase, create_user_Test) { SSqlInfo info1 = doGenerateAST(sql); ASSERT_EQ(info1.valid, true); - ASSERT_EQ(isDdlSql(&info1), true); + ASSERT_EQ(isDclSqlStatement(&info1), true); void* output = NULL; int32_t type = 0; - - int32_t code = qParserValidateDdlSqlNode(&info1, 1, &output, &type, msg, buf.len); + int32_t len = 0; + int32_t code = qParserValidateDclSqlNode(&info1, 1, &output, &len, &type, msg, buf.len); ASSERT_EQ(code, 0); destroySqlInfo(&info1); From 275234aa2f8d20cd946cc5ee995b6fe5cc3be522 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 16 Dec 2021 15:52:07 +0800 Subject: [PATCH 4/4] [td-11818] merge 3.0 --- include/client/taos.h | 61 +++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/include/client/taos.h b/include/client/taos.h index 19d191b84e..f62abeb045 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -39,7 +39,7 @@ typedef void **TAOS_ROW; #define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes #define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes #define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes -#define TSDB_DATA_TYPE_BINARY 8 // string +#define TSDB_DATA_TYPE_BINARY 8 // string, alias for varchar #define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes #define TSDB_DATA_TYPE_NCHAR 10 // unicode string #define TSDB_DATA_TYPE_UTINYINT 11 // 1 byte @@ -47,10 +47,10 @@ typedef void **TAOS_ROW; #define TSDB_DATA_TYPE_UINT 13 // 4 bytes #define TSDB_DATA_TYPE_UBIGINT 14 // 8 bytes #define TSDB_DATA_TYPE_VARCHAR 15 // string -#define TSDB_DATA_TYPE_JSON 16 // json -#define TSDB_DATA_TYPE_DECIMAL 17 // decimal -#define TSDB_DATA_TYPE_BLOB 18 // binary string -#define TSDB_DATA_TYPE_LONGBLOB 19 // long binary string +#define TSDB_DATA_TYPE_VARBINARY 16 // binary +#define TSDB_DATA_TYPE_JSON 17 // json +#define TSDB_DATA_TYPE_DECIMAL 18 // decimal +#define TSDB_DATA_TYPE_BLOB 19 // binary typedef enum { TSDB_OPTION_LOCALE, @@ -61,6 +61,23 @@ typedef enum { TSDB_MAX_OPTIONS } TSDB_OPTION; +typedef enum { + TSDB_SML_UNKNOWN_PROTOCOL = 0, + TSDB_SML_LINE_PROTOCOL = 1, + TSDB_SML_TELNET_PROTOCOL = 2, + TSDB_SML_JSON_PROTOCOL = 3, +} TSDB_SML_PROTOCOL_TYPE; + +typedef enum { + TSDB_SML_TIMESTAMP_NOT_CONFIGURED = 0, + TSDB_SML_TIMESTAMP_HOURS, + TSDB_SML_TIMESTAMP_MINUTES, + TSDB_SML_TIMESTAMP_SECONDS, + TSDB_SML_TIMESTAMP_MILLI_SECONDS, + TSDB_SML_TIMESTAMP_MICRO_SECONDS, + TSDB_SML_TIMESTAMP_NANO_SECONDS, +} TSDB_SML_TIMESTAMP_TYPE; + typedef struct taosField { char name[65]; uint8_t type; @@ -136,37 +153,36 @@ DLL_EXPORT int taos_stmt_close(TAOS_STMT *stmt); DLL_EXPORT char * taos_stmt_errstr(TAOS_STMT *stmt); DLL_EXPORT TAOS_RES *taos_query(TAOS *taos, const char *sql); +DLL_EXPORT TAOS_RES *taos_query_l(TAOS *taos, const char *sql, size_t sqlLen); + DLL_EXPORT TAOS_ROW taos_fetch_row(TAOS_RES *res); -DLL_EXPORT int taos_result_precision(TAOS_RES *res); // get the time precision of result +DLL_EXPORT int taos_result_precision(TAOS_RES *res); // get the time precision of result DLL_EXPORT void taos_free_result(TAOS_RES *res); -DLL_EXPORT int taos_field_count(TAOS_RES *res); -DLL_EXPORT int taos_num_fields(TAOS_RES *res); -DLL_EXPORT int taos_affected_rows(TAOS_RES *res); +DLL_EXPORT int taos_field_count(TAOS_RES *res); +DLL_EXPORT int taos_num_fields(TAOS_RES *res); +DLL_EXPORT int taos_affected_rows(TAOS_RES *res); + DLL_EXPORT TAOS_FIELD *taos_fetch_fields(TAOS_RES *res); -DLL_EXPORT int taos_select_db(TAOS *taos, const char *db); -DLL_EXPORT int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields); +DLL_EXPORT int taos_select_db(TAOS *taos, const char *db); +DLL_EXPORT int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields); DLL_EXPORT void taos_stop_query(TAOS_RES *res); DLL_EXPORT bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col); -DLL_EXPORT int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows); -DLL_EXPORT int taos_validate_sql(TAOS *taos, const char *sql); +DLL_EXPORT int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows); +DLL_EXPORT int taos_validate_sql(TAOS *taos, const char *sql); DLL_EXPORT int* taos_fetch_lengths(TAOS_RES *res); -// TAOS_RES *taos_list_tables(TAOS *mysql, const char *wild); -// TAOS_RES *taos_list_dbs(TAOS *mysql, const char *wild); - -// TODO: the return value should be `const` DLL_EXPORT const char *taos_get_server_info(TAOS *taos); DLL_EXPORT const char *taos_get_client_info(); -DLL_EXPORT const char *taos_errstr(TAOS_RES *tres); -DLL_EXPORT int taos_errno(TAOS_RES *tres); +DLL_EXPORT const char *taos_errstr(TAOS_RES *tres); +DLL_EXPORT int taos_errno(TAOS_RES *tres); DLL_EXPORT void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param); DLL_EXPORT void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param); -typedef void (*TAOS_SUBSCRIBE_CALLBACK)(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code); -DLL_EXPORT TAOS_SUB *taos_subscribe(TAOS* taos, int restart, const char* topic, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval); +typedef void (*__taos_sub_fn_t)(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code); +DLL_EXPORT TAOS_SUB *taos_subscribe(TAOS* taos, int restart, const char* topic, const char *sql, __taos_sub_fn_t fp, void *param, int interval); DLL_EXPORT TAOS_RES *taos_consume(TAOS_SUB *tsub); DLL_EXPORT void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress); @@ -175,8 +191,7 @@ DLL_EXPORT TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sql, void (*fp) DLL_EXPORT void taos_close_stream(TAOS_STREAM *tstr); DLL_EXPORT int taos_load_table_info(TAOS *taos, const char* tableNameList); - -DLL_EXPORT int taos_insert_lines(TAOS* taos, char* lines[], int numLines); +DLL_EXPORT TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int protocol, int precision); #ifdef __cplusplus }