[td-11818] support use db/create stable.
This commit is contained in:
parent
969d96449d
commit
42903d3d1f
|
@ -95,15 +95,15 @@ TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_NETWORK_TEST, "nettest" )
|
|||
|
||||
// message from mnode to vnode
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CREATE_STB_IN, "create-stb-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_ALTER_STB_IN, "alter-stb-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_ALTER_STB_IN, "alter-stb-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DROP_STB_IN, "drop-stb-internal" )
|
||||
// message from mnode to mnode
|
||||
// message from mnode to qnode
|
||||
// message from mnode to dnode
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CREATE_VNODE_IN, "create-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_ALTER_VNODE_IN, "alter-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DROP_VNODE_IN, "drop-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_AUTH_VNODE_IN, "auth-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DROP_VNODE_IN, "drop-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_AUTH_VNODE_IN, "auth-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_SYNC_VNODE_IN, "sync-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_COMPACT_VNODE_IN, "compact-vnode-internal" )
|
||||
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CREATE_MNODE_IN, "create-mnode-internal" )
|
||||
|
@ -290,6 +290,37 @@ typedef struct SSchema {
|
|||
char name[TSDB_COL_NAME_LEN];
|
||||
} SSchema;
|
||||
|
||||
typedef struct {
|
||||
int32_t contLen;
|
||||
int32_t vgId;
|
||||
int8_t tableType;
|
||||
int16_t numOfColumns;
|
||||
int16_t numOfTags;
|
||||
int32_t tid;
|
||||
int32_t sversion;
|
||||
int32_t tversion;
|
||||
int32_t tagDataLen;
|
||||
int32_t sqlDataLen;
|
||||
uint64_t uid;
|
||||
uint64_t superTableUid;
|
||||
uint64_t createdTime;
|
||||
char tableFname[TSDB_TABLE_FNAME_LEN];
|
||||
char stbFname[TSDB_TABLE_FNAME_LEN];
|
||||
char data[];
|
||||
} SMDCreateTableMsg;
|
||||
|
||||
typedef struct {
|
||||
int32_t len; // one create table message
|
||||
char tableName[TSDB_TABLE_FNAME_LEN];
|
||||
int16_t numOfTags;
|
||||
int16_t numOfColumns;
|
||||
int16_t sqlLen; // the length of SQL, it starts after schema , sql is a null-terminated string
|
||||
int8_t igExists;
|
||||
int8_t rspMeta;
|
||||
int8_t reserved[16];
|
||||
char schema[];
|
||||
} SCreateTableMsg;
|
||||
|
||||
typedef struct {
|
||||
char name[TSDB_TABLE_FNAME_LEN];
|
||||
int8_t igExists;
|
||||
|
@ -327,19 +358,6 @@ typedef struct {
|
|||
uint64_t suid;
|
||||
} SDropStbInternalMsg;
|
||||
|
||||
typedef struct {
|
||||
SMsgHead head;
|
||||
char name[TSDB_TABLE_FNAME_LEN];
|
||||
char stbFname[TSDB_TABLE_FNAME_LEN];
|
||||
int8_t tableType;
|
||||
uint64_t suid;
|
||||
int32_t sversion;
|
||||
int32_t numOfTags;
|
||||
int32_t numOfColumns;
|
||||
int32_t tagDataLen;
|
||||
char data[];
|
||||
} SCreateTableMsg;
|
||||
|
||||
typedef struct {
|
||||
SMsgHead head;
|
||||
char name[TSDB_TABLE_FNAME_LEN];
|
||||
|
|
|
@ -102,14 +102,6 @@ enum {
|
|||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_MAX, "max" )
|
||||
};
|
||||
|
||||
// create table operation type
|
||||
enum TSQL_CREATE_TABLE_TYPE {
|
||||
TSQL_CREATE_TABLE = 0x1,
|
||||
TSQL_CREATE_STABLE = 0x2,
|
||||
TSQL_CREATE_CTABLE = 0x3,
|
||||
TSQL_CREATE_STREAM = 0x4,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#ifndef TDENGINE_TNAME_H
|
||||
#define TDENGINE_TNAME_H
|
||||
|
||||
//#include "taosmsg.h"
|
||||
|
||||
#define TSDB_DB_NAME_T 1
|
||||
#define TSDB_TABLE_NAME_T 2
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
typedef struct SField {
|
||||
char name[TSDB_COL_NAME_LEN];
|
||||
uint8_t type;
|
||||
int16_t bytes;
|
||||
int32_t bytes;
|
||||
} SField;
|
||||
|
||||
typedef struct SFieldInfo {
|
||||
|
@ -38,6 +38,13 @@ typedef struct SFieldInfo {
|
|||
SArray *internalField; // SArray<SInternalField>
|
||||
} SFieldInfo;
|
||||
|
||||
// TODO merged with SParseContext
|
||||
typedef struct SParseCtx {
|
||||
char *db;
|
||||
int32_t acctId;
|
||||
uint64_t requestId;
|
||||
} SParseCtx;
|
||||
|
||||
typedef struct SCond {
|
||||
uint64_t uid;
|
||||
int32_t len; // length of tag query condition data
|
||||
|
@ -153,7 +160,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, int32_t* outputLen, char* msg, int32_t msgLen);
|
||||
int32_t qParseQuerySql(const char* pStr, size_t length, SParseCtx* pParseCtx, int32_t* type, void** pOutput, int32_t* outputLen, char* msg, int32_t msgLen);
|
||||
|
||||
typedef enum {
|
||||
PAYLOAD_TYPE_KV = 0,
|
||||
|
|
|
@ -148,8 +148,11 @@ int taos_init();
|
|||
void* createTscObj(const char* user, const char* auth, const char *ip, uint32_t port, SAppInstInfo* pAppInfo);
|
||||
void destroyTscObj(void*pObj);
|
||||
|
||||
void* createRequest(STscObj* pObj, __taos_async_fn_t fp, void* param, int32_t type);
|
||||
void destroyRequest(SRequestObj* pRequest);
|
||||
void *createRequest(STscObj* pObj, __taos_async_fn_t fp, void* param, int32_t type);
|
||||
void destroyRequest(SRequestObj* pRequest);
|
||||
|
||||
char *getConnectionDB(STscObj* pObj);
|
||||
void setConnectionDB(STscObj* pTscObj, const char* db);
|
||||
|
||||
void taos_init_imp(void);
|
||||
int taos_options_imp(TSDB_OPTION option, const char *str);
|
||||
|
|
|
@ -151,8 +151,12 @@ TAOS_RES *taos_query_l(TAOS *taos, const char *sql, int sqlLen) {
|
|||
int32_t type = 0;
|
||||
void* output = NULL;
|
||||
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 || type == TSDB_SQL_DROP_USER || type == TSDB_SQL_DROP_ACCT || type == TSDB_SQL_CREATE_DB || type == TSDB_SQL_CREATE_ACCT) {
|
||||
|
||||
SParseCtx c = {.requestId = pRequest->requestId, .acctId = pTscObj->acctId, .db = getConnectionDB(pTscObj)};
|
||||
code = qParseQuerySql(pRequest->sqlstr, sqlLen, &c, &type, &output, &outputLen, pRequest->msgBuf, ERROR_MSG_BUF_DEFAULT_SIZE);
|
||||
if (type == TSDB_SQL_CREATE_USER || type == TSDB_SQL_SHOW || type == TSDB_SQL_DROP_USER ||
|
||||
type == TSDB_SQL_DROP_ACCT || type == TSDB_SQL_CREATE_DB || type == TSDB_SQL_CREATE_ACCT ||
|
||||
type == TSDB_SQL_CREATE_TABLE || type == TSDB_SQL_USE_DB) {
|
||||
pRequest->type = type;
|
||||
pRequest->body.requestMsg = (SReqMsgInfo){.pMsg = output, .len = outputLen};
|
||||
|
||||
|
@ -169,6 +173,8 @@ TAOS_RES *taos_query_l(TAOS *taos, const char *sql, int sqlLen) {
|
|||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tfree(c.db);
|
||||
}
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -436,8 +442,19 @@ void setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32_t
|
|||
}
|
||||
}
|
||||
|
||||
const char *taos_get_client_info() { return version; }
|
||||
char* getConnectionDB(STscObj* pObj) {
|
||||
char *p = NULL;
|
||||
pthread_mutex_lock(&pObj->mutex);
|
||||
p = strndup(pObj->db, tListLen(pObj->db));
|
||||
pthread_mutex_unlock(&pObj->mutex);
|
||||
|
||||
int taos_affected_rows(TAOS_RES *res) { return 1; }
|
||||
return p;
|
||||
}
|
||||
|
||||
void setConnectionDB(STscObj* pTscObj, const char* db) {
|
||||
assert(db != NULL && pTscObj != NULL);
|
||||
pthread_mutex_lock(&pTscObj->mutex);
|
||||
tstrncpy(pTscObj->db, db, tListLen(pTscObj->db));
|
||||
pthread_mutex_unlock(&pTscObj->mutex);
|
||||
}
|
||||
|
||||
int taos_result_precision(TAOS_RES *res) { return TSDB_TIME_PRECISION_MILLI; }
|
||||
|
|
|
@ -255,3 +255,9 @@ const char *taos_data_type(int type) {
|
|||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
const char *taos_get_client_info() { return version; }
|
||||
|
||||
int taos_affected_rows(TAOS_RES *res) { return 1; }
|
||||
|
||||
int taos_result_precision(TAOS_RES *res) { return TSDB_TIME_PRECISION_MILLI; }
|
||||
|
|
|
@ -2891,7 +2891,14 @@ int32_t doBuildMsgSupp(SRequestObj *pRequest, SRequestMsgBody* pMsgBody) {
|
|||
}
|
||||
|
||||
tNameGetFullDbName(&name, pCreateMsg->db);
|
||||
|
||||
break;
|
||||
}
|
||||
case TSDB_SQL_USE_DB: {
|
||||
pMsgBody->msgType = TSDB_MSG_TYPE_USE_DB;
|
||||
break;
|
||||
}
|
||||
case TSDB_SQL_CREATE_TABLE: {
|
||||
pMsgBody->msgType = TSDB_MSG_TYPE_CREATE_STB;
|
||||
break;
|
||||
}
|
||||
case TSDB_SQL_SHOW:
|
||||
|
@ -2973,6 +2980,20 @@ int32_t processCreateDbRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgL
|
|||
// todo rsp with the vnode id list
|
||||
}
|
||||
|
||||
int32_t processUseDbRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) {
|
||||
SUseDbRsp* pUseDbRsp = (SUseDbRsp*) pMsg;
|
||||
SName name = {0};
|
||||
tNameFromString(&name, pUseDbRsp->db, T_NAME_ACCT|T_NAME_DB);
|
||||
|
||||
char db[TSDB_DB_NAME_LEN] = {0};
|
||||
tNameGetDbName(&name, db);
|
||||
setConnectionDB(pRequest->pTscObj, db);
|
||||
}
|
||||
|
||||
int32_t processCreateTableRsp(SRequestObj *pRequest, const char* pMsg, int32_t msgLen) {
|
||||
assert(pMsg != NULL);
|
||||
}
|
||||
|
||||
void initMsgHandleFp() {
|
||||
#if 0
|
||||
tscBuildMsg[TSDB_SQL_SELECT] = tscBuildQueryMsg;
|
||||
|
@ -3066,4 +3087,10 @@ void initMsgHandleFp() {
|
|||
|
||||
buildRequestMsgFp[TSDB_SQL_CREATE_DB] = doBuildMsgSupp;
|
||||
handleRequestRspFp[TSDB_SQL_CREATE_DB] = processCreateDbRsp;
|
||||
|
||||
buildRequestMsgFp[TSDB_SQL_USE_DB] = doBuildMsgSupp;
|
||||
handleRequestRspFp[TSDB_SQL_USE_DB] = processUseDbRsp;
|
||||
|
||||
buildRequestMsgFp[TSDB_SQL_CREATE_TABLE] = doBuildMsgSupp;
|
||||
handleRequestRspFp[TSDB_SQL_CREATE_TABLE] = processCreateTableRsp;
|
||||
}
|
|
@ -16,15 +16,15 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <taoserror.h>
|
||||
#include <iostream>
|
||||
#include "tglobal.h"
|
||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
#include "../inc/clientInt.h"
|
||||
#include "taos.h"
|
||||
#include "tglobal.h"
|
||||
#include "../inc/clientInt.h"
|
||||
|
||||
namespace {
|
||||
} // namespace
|
||||
|
@ -149,11 +149,29 @@ TEST(testCase, create_db_Test) {
|
|||
taos_close(pConn);
|
||||
}
|
||||
|
||||
TEST(testCase, create_stable_Test) {
|
||||
TEST(testCase, use_db_test) {
|
||||
TAOS* pConn = taos_connect("ubuntu", "root", "taosdata", NULL, 0);
|
||||
assert(pConn != NULL);
|
||||
|
||||
TAOS_RES* pRes = taos_query(pConn, "create stable st1(ts timestamp, k int) tags(a int)");
|
||||
TAOS_RES* pRes = taos_query(pConn, "use abc1");
|
||||
|
||||
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
|
||||
ASSERT_TRUE(pFields == NULL);
|
||||
|
||||
int32_t numOfFields = taos_num_fields(pRes);
|
||||
ASSERT_EQ(numOfFields, 0);
|
||||
|
||||
taos_close(pConn);
|
||||
}
|
||||
|
||||
TEST(testCase, create_stable_Test) {
|
||||
TAOS* pConn = taos_connect("ubuntu", "root", "taosdata", NULL, 0);
|
||||
assert(pConn != NULL);
|
||||
|
||||
TAOS_RES* pRes = taos_query(pConn, "use abc1");
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create stable st1(ts timestamp, k int) tags(a int)");
|
||||
|
||||
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
|
||||
ASSERT_TRUE(pFields == NULL);
|
||||
|
|
|
@ -6,21 +6,6 @@
|
|||
|
||||
#define VALID_NAME_TYPE(x) ((x) == TSDB_DB_NAME_T || (x) == TSDB_TABLE_NAME_T)
|
||||
|
||||
char* extractDBName(const char* tableId, char* name) {
|
||||
size_t offset1 = strcspn(tableId, &TS_PATH_DELIMITER[0]);
|
||||
size_t len = strcspn(&tableId[offset1 + 1], &TS_PATH_DELIMITER[0]);
|
||||
|
||||
return strncpy(name, &tableId[offset1 + 1], len);
|
||||
}
|
||||
|
||||
// todo remove it
|
||||
size_t tableIdPrefix(const char* name, char* prefix, int32_t len) {
|
||||
tstrncpy(prefix, name, len);
|
||||
strcat(prefix, TS_PATH_DELIMITER);
|
||||
|
||||
return strlen(prefix);
|
||||
}
|
||||
|
||||
bool tscValidateTableNameLength(size_t len) {
|
||||
return len < TSDB_TABLE_NAME_LEN;
|
||||
}
|
||||
|
@ -125,7 +110,7 @@ int32_t tNameExtractFullName(const SName* name, char* dst) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int32_t len = snprintf(dst, TSDB_FULL_DB_NAME_LEN, "%s.%s", name->acctId, name->dbname);
|
||||
int32_t len = snprintf(dst, TSDB_FULL_DB_NAME_LEN, "%d.%s", name->acctId, name->dbname);
|
||||
|
||||
size_t tnameLen = strlen(name->tname);
|
||||
if (tnameLen > 0) {
|
||||
|
@ -141,7 +126,9 @@ int32_t tNameExtractFullName(const SName* name, char* dst) {
|
|||
|
||||
int32_t tNameLen(const SName* name) {
|
||||
assert(name != NULL);
|
||||
int32_t len = (int32_t) strlen(name->acctId);
|
||||
|
||||
char tmp[12] = {0};
|
||||
int32_t len = sprintf(tmp, "%d", name->acctId);
|
||||
int32_t len1 = (int32_t) strlen(name->dbname);
|
||||
int32_t len2 = (int32_t) strlen(name->tname);
|
||||
|
||||
|
@ -161,10 +148,6 @@ bool tNameIsValid(const SName* name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (strlen(name->acctId) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name->type == TSDB_DB_NAME_T) {
|
||||
return strlen(name->dbname) > 0;
|
||||
} else {
|
||||
|
@ -237,13 +220,6 @@ int32_t tNameFromString(SName* dst, const char* str, uint32_t type) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int32_t len = (int32_t)(p - str);
|
||||
|
||||
// too long account id or too long db name
|
||||
// if ((len >= tListLen(dst->acctId)) || (len <= 0)) {
|
||||
// return -1;
|
||||
// }
|
||||
// memcpy (dst->acctId, str, len);
|
||||
dst->acctId = strtoll(str, NULL, 10);
|
||||
}
|
||||
|
||||
|
@ -272,9 +248,8 @@ int32_t tNameFromString(SName* dst, const char* str, uint32_t type) {
|
|||
dst->type = TSDB_TABLE_NAME_T;
|
||||
char* start = (char*) ((p == NULL)? str: (p+1));
|
||||
|
||||
int32_t len = (int32_t) strlen(start);
|
||||
|
||||
// too long account id or too long db name
|
||||
int32_t len = (int32_t) strlen(start);
|
||||
if ((len >= tListLen(dst->tname)) || (len <= 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -9,5 +9,6 @@ SCreateAcctMsg* buildAcctManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, in
|
|||
SDropUserMsg* buildDropUserMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen);
|
||||
SShowMsg* buildShowMsg(SShowInfo* pShowInfo, int64_t id, char* msgBuf, int32_t msgLen);
|
||||
SCreateDbMsg* buildCreateDbMsg(SCreateDbInfo* pCreateDbInfo, char* msgBuf, int32_t msgLen);
|
||||
SCreateStbMsg* buildCreateTableMsg(SCreateTableSql* pCreateTableSql, int32_t* len, SParseCtx* pParseCtx, SMsgBuf* pMsgBuf);
|
||||
|
||||
#endif // TDENGINE_ASTTOMSG_H
|
||||
|
|
|
@ -38,6 +38,14 @@ typedef struct SMsgBuf {
|
|||
char *buf;
|
||||
} SMsgBuf;
|
||||
|
||||
// create table operation type
|
||||
enum TSQL_CREATE_TABLE_TYPE {
|
||||
TSQL_CREATE_TABLE = 0x1,
|
||||
TSQL_CREATE_STABLE = 0x2,
|
||||
TSQL_CREATE_CTABLE = 0x3,
|
||||
TSQL_CREATE_STREAM = 0x4,
|
||||
};
|
||||
|
||||
void clearTableMetaInfo(STableMetaInfo* pTableMetaInfo);
|
||||
|
||||
void clearAllTableMetaInfo(SQueryStmtInfo* pQueryInfo, bool removeMeta, uint64_t id);
|
||||
|
@ -60,7 +68,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pSqlInfo, SQ
|
|||
* @param type
|
||||
* @return
|
||||
*/
|
||||
int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, int32_t* outputLen, int32_t* type, char* msgBuf, int32_t msgBufLen);
|
||||
int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseCtx* pCtx, void** output, int32_t* outputLen, int32_t* type, char* msgBuf, int32_t msgBufLen);
|
||||
|
||||
/**
|
||||
* Evaluate the numeric and timestamp arithmetic expression in the WHERE clause.
|
||||
|
|
|
@ -68,6 +68,7 @@ STableMeta* tableMetaDup(const STableMeta* pTableMeta);
|
|||
|
||||
bool isDclSqlStatement(SSqlInfo* pSqlInfo);
|
||||
bool isDdlSqlStatement(SSqlInfo* pSqlInfo);
|
||||
bool isDqlSqlStatement(SSqlInfo* pSqlInfo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "taos.h"
|
||||
#include "os.h"
|
||||
#include "astGenerator.h"
|
||||
#include <parserInt.h>
|
||||
#include "os.h"
|
||||
#include "taos.h"
|
||||
#include "tmsgtype.h"
|
||||
|
||||
SArray *tListItemAppend(SArray *pList, SVariant *pVar, uint8_t sortOrder) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <astGenerator.h>
|
||||
#include "parserInt.h"
|
||||
#include "parserUtil.h"
|
||||
|
||||
|
@ -219,3 +220,126 @@ SCreateDbMsg* buildCreateDbMsg(SCreateDbInfo* pCreateDbInfo, char* msgBuf, int32
|
|||
|
||||
return pCreateMsg;
|
||||
}
|
||||
|
||||
int32_t createSName(SName* pName, SToken* pTableName, SParseCtx* pParseCtx, SMsgBuf* pMsgBuf) {
|
||||
const char* msg1 = "name too long";
|
||||
const char* msg2 = "acctId too long";
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
char* p = strnchr(pTableName->z, TS_PATH_DELIMITER[0], pTableName->n, false);
|
||||
|
||||
if (p != NULL) { // db has been specified in sql string so we ignore current db path
|
||||
code = tNameSetAcctId(pName, pParseCtx->acctId);
|
||||
if (code != 0) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg2);
|
||||
}
|
||||
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
strncpy(name, pTableName->z, pTableName->n);
|
||||
|
||||
code = tNameFromString(pName, name, T_NAME_DB|T_NAME_TABLE);
|
||||
if (code != 0) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
} else { // get current DB name first, and then set it into path
|
||||
if (pTableName->n >= TSDB_TABLE_NAME_LEN) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
tNameSetDbName(pName, pParseCtx->acctId, pParseCtx->db, strlen(pParseCtx->db));
|
||||
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
strncpy(name, pTableName->z, pTableName->n);
|
||||
|
||||
code = tNameFromString(pName, name, T_NAME_TABLE);
|
||||
if (code != 0) {
|
||||
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
SCreateStbMsg* buildCreateTableMsg(SCreateTableSql* pCreateTableSql, int32_t* len, SParseCtx* pParseCtx, SMsgBuf* pMsgBuf) {
|
||||
SSchema* pSchema;
|
||||
|
||||
int32_t numOfCols = (int32_t) taosArrayGetSize(pCreateTableSql->colInfo.pColumns);
|
||||
int32_t numOfTags = (int32_t) taosArrayGetSize(pCreateTableSql->colInfo.pTagColumns);
|
||||
|
||||
SCreateStbMsg* pCreateTableMsg = (SCreateStbMsg*)calloc(1, sizeof(SCreateStbMsg) + (numOfCols + numOfTags) * sizeof(SSchema));
|
||||
|
||||
char* pMsg = NULL;
|
||||
int8_t type = pCreateTableSql->type;
|
||||
if (type == TSQL_CREATE_TABLE) { // create by using super table, tags value
|
||||
#if 0
|
||||
SArray* list = pInfo->pCreateTableInfo->childTableInfo;
|
||||
|
||||
int32_t numOfTables = (int32_t)taosArrayGetSize(list);
|
||||
pCreateTableMsg->numOfTables = htonl(numOfTables);
|
||||
|
||||
pMsg = (char*)pCreateMsg;
|
||||
for (int32_t i = 0; i < numOfTables; ++i) {
|
||||
SCreateTableMsg* pCreate = (SCreateTableMsg*)pMsg;
|
||||
|
||||
pCreate->numOfColumns = htons(pCmd->numOfCols);
|
||||
pCreate->numOfTags = htons(pCmd->count);
|
||||
pMsg += sizeof(SCreateTableMsg);
|
||||
|
||||
SCreatedTableInfo* p = taosArrayGet(list, i);
|
||||
strcpy(pCreate->tableName, p->fullname);
|
||||
pCreate->igExists = (p->igExist) ? 1 : 0;
|
||||
|
||||
// use dbinfo from table id without modifying current db info
|
||||
pMsg = serializeTagData(&p->tagdata, pMsg);
|
||||
|
||||
int32_t len = (int32_t)(pMsg - (char*)pCreate);
|
||||
pCreate->len = htonl(len);
|
||||
}
|
||||
#endif
|
||||
} else { // create (super) table
|
||||
SName n = {0};
|
||||
int32_t code = createSName(&n, &pCreateTableSql->name, pParseCtx, pMsgBuf);
|
||||
if (code != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
code = tNameExtractFullName(&n, pCreateTableMsg->name);
|
||||
if (code != 0) {
|
||||
buildInvalidOperationMsg(pMsgBuf, "invalid table name or database not specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pCreateTableMsg->igExists = pCreateTableSql->existCheck ? 1 : 0;
|
||||
|
||||
pCreateTableMsg->numOfColumns = htonl(numOfCols);
|
||||
pCreateTableMsg->numOfTags = htonl(numOfTags);
|
||||
|
||||
pSchema = (SSchema*) pCreateTableMsg->pSchema;
|
||||
for (int i = 0; i < numOfCols; ++i) {
|
||||
TAOS_FIELD* pField = taosArrayGet(pCreateTableSql->colInfo.pColumns, i);
|
||||
|
||||
pSchema->type = pField->type;
|
||||
pSchema->bytes = htonl(pField->bytes);
|
||||
strcpy(pSchema->name, pField->name);
|
||||
|
||||
pSchema++;
|
||||
}
|
||||
|
||||
for(int32_t i = 0; i < numOfTags; ++i) {
|
||||
TAOS_FIELD* pField = taosArrayGet(pCreateTableSql->colInfo.pTagColumns, i);
|
||||
|
||||
pSchema->type = pField->type;
|
||||
pSchema->bytes = htonl(pField->bytes);
|
||||
strcpy(pSchema->name, pField->name);
|
||||
|
||||
pSchema++;
|
||||
}
|
||||
|
||||
pMsg = (char*)pSchema;
|
||||
}
|
||||
|
||||
int32_t msgLen = (int32_t)(pMsg - (char*)pCreateTableMsg);
|
||||
*len = msgLen;
|
||||
|
||||
return pCreateTableMsg;
|
||||
}
|
||||
|
|
|
@ -4171,7 +4171,144 @@ static int32_t doCheckDbOptions(SCreateDbMsg* pCreate, SMsgBuf* pMsgBuf) {
|
|||
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) {
|
||||
/* is contained in pFieldList or not */
|
||||
static bool has(SArray* pFieldList, int32_t startIndex, const char* name) {
|
||||
size_t numOfCols = taosArrayGetSize(pFieldList);
|
||||
for (int32_t j = startIndex; j < numOfCols; ++j) {
|
||||
TAOS_FIELD* field = taosArrayGet(pFieldList, j);
|
||||
if (strncasecmp(name, field->name, sizeof(field->name) - 1) == 0) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t validateTableColumns(SArray* pFieldList, int32_t maxRowLength, int32_t maxColumns, SMsgBuf* pMsgBuf) {
|
||||
const char* msg2 = "row length exceeds max length";
|
||||
const char* msg3 = "duplicated column names";
|
||||
const char* msg4 = "invalid data type";
|
||||
const char* msg5 = "invalid binary/nchar column length";
|
||||
const char* msg6 = "invalid column name";
|
||||
const char* msg7 = "too many columns";
|
||||
const char* msg8 = "illegal number of columns";
|
||||
|
||||
size_t numOfCols = taosArrayGetSize(pFieldList);
|
||||
if (numOfCols > maxColumns) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg7);
|
||||
}
|
||||
|
||||
int32_t rowLen = 0;
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
TAOS_FIELD* pField = taosArrayGet(pFieldList, i);
|
||||
if (!isValidDataType(pField->type)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg4);
|
||||
}
|
||||
|
||||
if (pField->bytes == 0) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
|
||||
if ((pField->type == TSDB_DATA_TYPE_BINARY && (pField->bytes <= 0 || pField->bytes > TSDB_MAX_BINARY_LEN)) ||
|
||||
(pField->type == TSDB_DATA_TYPE_NCHAR && (pField->bytes <= 0 || pField->bytes > TSDB_MAX_NCHAR_LEN))) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
|
||||
SToken nameToken = {.z = pField->name, .n = strlen(pField->name), .type = TK_ID};
|
||||
if (parserValidateNameToken(&nameToken) != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg6);
|
||||
}
|
||||
|
||||
// field name must be unique
|
||||
if (has(pFieldList, i + 1, pField->name) == true) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
}
|
||||
|
||||
rowLen += pField->bytes;
|
||||
}
|
||||
|
||||
// max row length must be less than TSDB_MAX_BYTES_PER_ROW
|
||||
if (rowLen > maxRowLength) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg2);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t validateTableColumnInfo(SArray* pFieldList, SMsgBuf* pMsgBuf) {
|
||||
assert(pFieldList != NULL);
|
||||
|
||||
const char* msg1 = "first column must be timestamp";
|
||||
const char* msg2 = "row length exceeds max length";
|
||||
const char* msg3 = "duplicated column names";
|
||||
const char* msg4 = "invalid data type";
|
||||
const char* msg5 = "invalid binary/nchar column length";
|
||||
const char* msg6 = "invalid column name";
|
||||
const char* msg7 = "too many columns";
|
||||
const char* msg8 = "illegal number of columns";
|
||||
|
||||
// first column must be timestamp
|
||||
TAOS_FIELD* pField = taosArrayGet(pFieldList, 0);
|
||||
if (pField->type != TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
// number of fields no less than 2
|
||||
size_t numOfCols = taosArrayGetSize(pFieldList);
|
||||
if (numOfCols <= 1) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg8);
|
||||
}
|
||||
|
||||
return validateTableColumns(pFieldList, TSDB_MAX_BYTES_PER_ROW, TSDB_MAX_COLUMNS, pMsgBuf);
|
||||
}
|
||||
|
||||
static int32_t validateTagParams(SArray* pTagsList, SArray* pFieldList, SMsgBuf* pMsgBuf) {
|
||||
assert(pTagsList != NULL);
|
||||
|
||||
const char* msg1 = "invalid number of tag columns";
|
||||
const char* msg3 = "duplicated column names";
|
||||
|
||||
// number of fields at least 1
|
||||
size_t numOfTags = taosArrayGetSize(pTagsList);
|
||||
if (numOfTags < 1) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
// field name must be unique
|
||||
for (int32_t i = 0; i < numOfTags; ++i) {
|
||||
TAOS_FIELD* p = taosArrayGet(pTagsList, i);
|
||||
if (has(pFieldList, 0, p->name) == true) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
}
|
||||
}
|
||||
|
||||
return validateTableColumns(pFieldList, TSDB_MAX_TAGS_LEN, TSDB_MAX_TAGS, pMsgBuf);
|
||||
}
|
||||
|
||||
int32_t doCheckForCreateTable(SSqlInfo* pInfo, SMsgBuf* pMsgBuf) {
|
||||
const char* msg1 = "invalid table name";
|
||||
|
||||
SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
|
||||
|
||||
SArray* pFieldList = pCreateTable->colInfo.pColumns;
|
||||
SArray* pTagList = pCreateTable->colInfo.pTagColumns;
|
||||
assert(pFieldList != NULL);
|
||||
|
||||
// if sql specifies db, use it, otherwise use default db
|
||||
SToken* pzTableName = &(pCreateTable->name);
|
||||
|
||||
bool dbIncluded = false;
|
||||
if (parserValidateNameToken(pzTableName) != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
if (validateTableColumnInfo(pFieldList, pMsgBuf) != TSDB_CODE_SUCCESS ||
|
||||
(pTagList != NULL && validateTagParams(pTagList, pFieldList, pMsgBuf) != TSDB_CODE_SUCCESS)) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseCtx* pCtx, void** output, int32_t* outputLen, int32_t* type, char* msgBuf, int32_t msgBufLen) {
|
||||
int32_t code = 0;
|
||||
|
||||
SMsgBuf m = {.buf = msgBuf, .len = msgBufLen};
|
||||
|
@ -4224,7 +4361,7 @@ int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, in
|
|||
}
|
||||
}
|
||||
|
||||
*output = buildUserManipulationMsg(pInfo, outputLen, id, msgBuf, msgBufLen);
|
||||
*output = buildUserManipulationMsg(pInfo, outputLen, pCtx->requestId, msgBuf, msgBufLen);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4260,13 +4397,13 @@ int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, in
|
|||
}
|
||||
}
|
||||
|
||||
*output = buildAcctManipulationMsg(pInfo, outputLen, id, msgBuf, msgBufLen);
|
||||
*output = buildAcctManipulationMsg(pInfo, outputLen, pCtx->requestId, msgBuf, msgBufLen);
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_SQL_DROP_ACCT:
|
||||
case TSDB_SQL_DROP_USER: {
|
||||
*output = buildDropUserMsg(pInfo, outputLen, id, msgBuf, msgBufLen);
|
||||
*output = buildDropUserMsg(pInfo, outputLen, pCtx->requestId, msgBuf, msgBufLen);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4275,6 +4412,28 @@ int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, in
|
|||
break;
|
||||
}
|
||||
|
||||
case TSDB_SQL_USE_DB: {
|
||||
const char* msg = "invalid db name";
|
||||
|
||||
SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
if (parserValidateNameToken(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
||||
}
|
||||
|
||||
SName n = {0};
|
||||
int32_t ret = tNameSetDbName(&n, pCtx->acctId, pToken->z, pToken->n);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
||||
}
|
||||
|
||||
SUseDbMsg *pUseDbMsg = (SUseDbMsg *) calloc(1, sizeof(SUseDbMsg));
|
||||
tNameExtractFullName(&n, pUseDbMsg->db);
|
||||
|
||||
*output = pUseDbMsg;
|
||||
*outputLen = sizeof(SUseDbMsg);
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_SQL_ALTER_DB:
|
||||
case TSDB_SQL_CREATE_DB: {
|
||||
const char* msg1 = "invalid db name";
|
||||
|
@ -4304,6 +4463,26 @@ int32_t qParserValidateDclSqlNode(SSqlInfo* pInfo, int64_t id, void** output, in
|
|||
break;
|
||||
}
|
||||
|
||||
case TSDB_SQL_CREATE_TABLE: {
|
||||
SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
|
||||
|
||||
if (pCreateTable->type == TSQL_CREATE_TABLE || pCreateTable->type == TSQL_CREATE_STABLE) {
|
||||
if ((code = doCheckForCreateTable(pInfo, pMsgBuf)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
*output = buildCreateTableMsg(pCreateTable, outputLen, pCtx, pMsgBuf);
|
||||
} else if (pCreateTable->type == TSQL_CREATE_CTABLE) {
|
||||
// if ((code = doCheckForCreateFromStable(pSql, pInfo)) != TSDB_CODE_SUCCESS) {
|
||||
// return code;
|
||||
// }
|
||||
|
||||
} else if (pCreateTable->type == TSQL_CREATE_STREAM) {
|
||||
// if ((code = doCheckForStream(pSql, pInfo)) != TSDB_CODE_SUCCESS) {
|
||||
// return code;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -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, int32_t* outputLen, char* msg, int32_t msgLen) {
|
||||
int32_t qParseQuerySql(const char* pStr, size_t length, SParseCtx* pParseCtx, int32_t *type, void** pOutput, int32_t* outputLen, char* msg, int32_t msgLen) {
|
||||
SSqlInfo info = doGenerateAST(pStr);
|
||||
if (!info.valid) {
|
||||
strncpy(msg, info.msg, msgLen);
|
||||
|
@ -39,8 +39,8 @@ int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t *typ
|
|||
return terrno;
|
||||
}
|
||||
|
||||
if (isDclSqlStatement(&info)) {
|
||||
int32_t code = qParserValidateDclSqlNode(&info, id, pOutput, outputLen, type, msg, msgLen);
|
||||
if (!isDqlSqlStatement(&info)) {
|
||||
int32_t code = qParserValidateDclSqlNode(&info, pParseCtx, pOutput, outputLen, type, msg, msgLen);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ int32_t qParseQuerySql(const char* pStr, size_t length, int64_t id, int32_t *typ
|
|||
|
||||
struct SCatalog* pCatalog = NULL;
|
||||
int32_t code = catalogGetHandle(NULL, &pCatalog);
|
||||
code = qParserValidateSqlNode(pCatalog, &info, pQueryInfo, id, msg, msgLen);
|
||||
code = qParserValidateSqlNode(pCatalog, &info, pQueryInfo, pParseCtx->requestId, msg, msgLen);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
*pOutput = pQueryInfo;
|
||||
}
|
||||
|
|
|
@ -1620,7 +1620,11 @@ bool isDclSqlStatement(SSqlInfo* pSqlInfo) {
|
|||
|
||||
bool isDdlSqlStatement(SSqlInfo* pSqlInfo) {
|
||||
int32_t type = pSqlInfo->type;
|
||||
return (type == TSDB_SQL_CREATE_TABLE || type == TSDB_SQL_CREATE_DB);
|
||||
return (type == TSDB_SQL_CREATE_TABLE || type == TSDB_SQL_CREATE_DB || type == TSDB_SQL_DROP_DB);
|
||||
}
|
||||
|
||||
bool isDqlSqlStatement(SSqlInfo* pSqlInfo) {
|
||||
return pSqlInfo->type == TSDB_SQL_SELECT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include "astGenerator.h"
|
||||
#include "parserInt.h"
|
||||
#include "tmsgtype.h"
|
||||
#include "ttoken.h"
|
||||
#include "ttokendef.h"
|
||||
|
|
|
@ -717,7 +717,9 @@ TEST(testCase, show_user_Test) {
|
|||
void* output = NULL;
|
||||
int32_t type = 0;
|
||||
int32_t len = 0;
|
||||
int32_t code = qParserValidateDclSqlNode(&info1, 1, &output, &len, &type, msg, buf.len);
|
||||
|
||||
SParseCtx ct= {.db= "abc", .acctId = 1, .requestId = 1};
|
||||
int32_t code = qParserValidateDclSqlNode(&info1, &ct, &output, &len, &type, msg, buf.len);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
// convert the show command to be the select query
|
||||
|
@ -734,13 +736,14 @@ TEST(testCase, create_user_Test) {
|
|||
|
||||
SSqlInfo info1 = doGenerateAST(sql);
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
ASSERT_EQ(isDclSqlStatement(&info1), true);
|
||||
|
||||
void* output = NULL;
|
||||
int32_t type = 0;
|
||||
int32_t len = 0;
|
||||
int32_t code = qParserValidateDclSqlNode(&info1, 1, &output, &len, &type, msg, buf.len);
|
||||
|
||||
SParseCtx ct= {.db= "abc", .acctId = 1, .requestId = 1};
|
||||
int32_t code = qParserValidateDclSqlNode(&info1, &ct, &output, &len, &type, msg, buf.len);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
destroySqlInfo(&info1);
|
||||
|
|
Loading…
Reference in New Issue