TD-13747 New SQL model integration
This commit is contained in:
parent
42d91c3dbb
commit
768e05939c
|
@ -23,6 +23,7 @@ extern "C" {
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "executor.h"
|
#include "executor.h"
|
||||||
|
#include "plannodes.h"
|
||||||
|
|
||||||
#define DS_BUF_LOW 1
|
#define DS_BUF_LOW 1
|
||||||
#define DS_BUF_FULL 2
|
#define DS_BUF_FULL 2
|
||||||
|
@ -59,7 +60,7 @@ typedef struct SOutputData {
|
||||||
* @param pHandle output
|
* @param pHandle output
|
||||||
* @return error code
|
* @return error code
|
||||||
*/
|
*/
|
||||||
int32_t dsCreateDataSinker(const struct SDataSink *pDataSink, DataSinkHandle* pHandle);
|
int32_t dsCreateDataSinker(const SDataSinkNode* pDataSink, DataSinkHandle* pHandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put the result set returned by the executor into datasinker.
|
* Put the result set returned by the executor into datasinker.
|
||||||
|
|
|
@ -70,6 +70,7 @@ typedef enum ENodeType {
|
||||||
QUERY_NODE_SET_OPERATOR,
|
QUERY_NODE_SET_OPERATOR,
|
||||||
QUERY_NODE_SELECT_STMT,
|
QUERY_NODE_SELECT_STMT,
|
||||||
QUERY_NODE_SHOW_STMT,
|
QUERY_NODE_SHOW_STMT,
|
||||||
|
QUERY_NODE_VNODE_MODIF_STMT,
|
||||||
|
|
||||||
// logic plan node
|
// logic plan node
|
||||||
QUERY_NODE_LOGIC_PLAN_SCAN,
|
QUERY_NODE_LOGIC_PLAN_SCAN,
|
||||||
|
@ -80,9 +81,15 @@ typedef enum ENodeType {
|
||||||
// physical plan node
|
// physical plan node
|
||||||
QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN,
|
QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN,
|
QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN,
|
||||||
|
QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN,
|
||||||
|
QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_PROJECT,
|
QUERY_NODE_PHYSICAL_PLAN_PROJECT,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_JOIN,
|
QUERY_NODE_PHYSICAL_PLAN_JOIN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_AGG
|
QUERY_NODE_PHYSICAL_PLAN_AGG,
|
||||||
|
QUERY_NODE_PHYSICAL_PLAN_EXCHANGE,
|
||||||
|
QUERY_NODE_PHYSICAL_PLAN_SORT,
|
||||||
|
|
||||||
|
QUERY_NODE_DSINK_DISPATCH
|
||||||
} ENodeType;
|
} ENodeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "querynodes.h"
|
#include "querynodes.h"
|
||||||
|
#include "query.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
|
|
||||||
typedef struct SLogicNode {
|
typedef struct SLogicNode {
|
||||||
|
@ -78,6 +79,8 @@ typedef struct SDataBlockDescNode {
|
||||||
ENodeType type;
|
ENodeType type;
|
||||||
int16_t dataBlockId;
|
int16_t dataBlockId;
|
||||||
SNodeList* pSlots;
|
SNodeList* pSlots;
|
||||||
|
int32_t resultRowSize;
|
||||||
|
int16_t precision;
|
||||||
} SDataBlockDescNode;
|
} SDataBlockDescNode;
|
||||||
|
|
||||||
typedef struct SPhysiNode {
|
typedef struct SPhysiNode {
|
||||||
|
@ -129,6 +132,34 @@ typedef struct SAggPhysiNode {
|
||||||
SNodeList* pAggFuncs;
|
SNodeList* pAggFuncs;
|
||||||
} SAggPhysiNode;
|
} SAggPhysiNode;
|
||||||
|
|
||||||
|
typedef struct SDownstreamSource {
|
||||||
|
SQueryNodeAddr addr;
|
||||||
|
uint64_t taskId;
|
||||||
|
uint64_t schedId;
|
||||||
|
} SDownstreamSource;
|
||||||
|
|
||||||
|
typedef struct SExchangePhysiNode {
|
||||||
|
SPhysiNode node;
|
||||||
|
uint64_t srcTemplateId; // template id of datasource suplans
|
||||||
|
SArray* pSrcEndPoints; // SArray<SDownstreamSource>, scheduler fill by calling qSetSuplanExecutionNode
|
||||||
|
} SExchangePhysiNode;
|
||||||
|
|
||||||
|
typedef struct SDataSinkNode {
|
||||||
|
ENodeType type;;
|
||||||
|
SDataBlockDescNode inputDataBlockDesc;
|
||||||
|
} SDataSinkNode;
|
||||||
|
|
||||||
|
typedef struct SDataDispatcherNode {
|
||||||
|
SDataSinkNode sink;
|
||||||
|
} SDataDispatcherNode;
|
||||||
|
|
||||||
|
typedef struct SDataInserterNode {
|
||||||
|
SDataSinkNode sink;
|
||||||
|
int32_t numOfTables;
|
||||||
|
uint32_t size;
|
||||||
|
char *pData;
|
||||||
|
} SDataInserterNode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
|
#include "tmsg.h"
|
||||||
|
|
||||||
typedef struct SRawExprNode {
|
typedef struct SRawExprNode {
|
||||||
ENodeType nodeType;
|
ENodeType nodeType;
|
||||||
|
@ -248,6 +249,28 @@ typedef enum ESqlClause {
|
||||||
SQL_CLAUSE_ORDER_BY
|
SQL_CLAUSE_ORDER_BY
|
||||||
} ESqlClause;
|
} ESqlClause;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PAYLOAD_TYPE_KV = 0,
|
||||||
|
PAYLOAD_TYPE_RAW = 1,
|
||||||
|
} EPayloadType;
|
||||||
|
|
||||||
|
typedef struct SVgDataBlocks {
|
||||||
|
SVgroupInfo vg;
|
||||||
|
int32_t numOfTables; // number of tables in current submit block
|
||||||
|
uint32_t size;
|
||||||
|
char *pData; // SMsgDesc + SSubmitReq + SSubmitBlk + ...
|
||||||
|
} SVgDataBlocks;
|
||||||
|
|
||||||
|
typedef struct SVnodeModifOpStmt {
|
||||||
|
ENodeType nodeType;
|
||||||
|
SArray* pDataBlocks; // data block for each vgroup, SArray<SVgDataBlocks*>.
|
||||||
|
int8_t schemaAttache; // denote if submit block is built with table schema or not
|
||||||
|
uint8_t payloadType; // EPayloadType. 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert
|
||||||
|
uint32_t insertType; // insert data from [file|sql statement| bound statement]
|
||||||
|
const char* sql; // current sql statement position
|
||||||
|
} SVnodeModifOpStmt;
|
||||||
|
|
||||||
void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext);
|
void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext);
|
||||||
void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext);
|
void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext);
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_NEW_PARSER_H_
|
|
||||||
#define _TD_NEW_PARSER_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
typedef enum EStmtType {
|
|
||||||
STMT_TYPE_CMD = 1,
|
|
||||||
STMT_TYPE_QUERY
|
|
||||||
} EStmtType;
|
|
||||||
|
|
||||||
typedef struct SQuery {
|
|
||||||
EStmtType stmtType;
|
|
||||||
SNode* pRoot;
|
|
||||||
int32_t numOfResCols;
|
|
||||||
SSchema* pResSchema;
|
|
||||||
} SQuery;
|
|
||||||
|
|
||||||
int32_t parser(SParseContext* pParseCxt, SQuery* pQuery);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*_TD_NEW_PARSER_H_*/
|
|
|
@ -1,163 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_PARSENODES_H_
|
|
||||||
#define _TD_PARSENODES_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "catalog.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "function.h"
|
|
||||||
#include "tmsgtype.h"
|
|
||||||
#include "tname.h"
|
|
||||||
#include "tvariant.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The first field of a node of any type is guaranteed to be the int16_t.
|
|
||||||
* Hence the type of any node can be gotten by casting it to SQueryNode.
|
|
||||||
*/
|
|
||||||
typedef struct SQueryNode {
|
|
||||||
int16_t type;
|
|
||||||
} SQueryNode;
|
|
||||||
|
|
||||||
#define queryNodeType(nodeptr) (((const SQueryNode*)(nodeptr))->type)
|
|
||||||
|
|
||||||
typedef struct SFieldInfo {
|
|
||||||
int16_t numOfOutput; // number of column in result
|
|
||||||
SField *final;
|
|
||||||
SArray *internalField; // SArray<SInternalField>
|
|
||||||
} SFieldInfo;
|
|
||||||
|
|
||||||
typedef struct SCond {
|
|
||||||
uint64_t uid;
|
|
||||||
int32_t len; // length of tag query condition data
|
|
||||||
char * cond;
|
|
||||||
} SCond;
|
|
||||||
|
|
||||||
typedef struct SJoinNode {
|
|
||||||
uint64_t uid;
|
|
||||||
int16_t tagColId;
|
|
||||||
SArray* tsJoin;
|
|
||||||
SArray* tagJoin;
|
|
||||||
} SJoinNode;
|
|
||||||
|
|
||||||
typedef struct SJoinInfo {
|
|
||||||
bool hasJoin;
|
|
||||||
SJoinNode *joinTables[TSDB_MAX_JOIN_TABLE_NUM];
|
|
||||||
} SJoinInfo;
|
|
||||||
|
|
||||||
typedef struct STagCond {
|
|
||||||
int16_t relType; // relation between tbname list and query condition, including : TK_AND or TK_OR
|
|
||||||
SCond tbnameCond; // tbname query condition, only support tbname query condition on one table
|
|
||||||
SJoinInfo joinInfo; // join condition, only support two tables join currently
|
|
||||||
SArray *pCond; // for different table, the query condition must be seperated
|
|
||||||
} STagCond;
|
|
||||||
|
|
||||||
typedef struct STableMetaInfo {
|
|
||||||
STableMeta *pTableMeta; // table meta, cached in client side and acquired by name
|
|
||||||
SVgroupsInfo *vgroupList;
|
|
||||||
SName name;
|
|
||||||
char aliasName[TSDB_TABLE_NAME_LEN]; // alias name of table specified in query sql
|
|
||||||
SArray *tagColList; // SArray<SColumn*>, involved tag columns
|
|
||||||
} STableMetaInfo;
|
|
||||||
|
|
||||||
typedef struct SColumnIndex {
|
|
||||||
int16_t tableIndex;
|
|
||||||
int16_t columnIndex;
|
|
||||||
int16_t type; // normal column/tag/ user input constant column
|
|
||||||
} SColumnIndex;
|
|
||||||
|
|
||||||
// select statement
|
|
||||||
typedef struct SQueryStmtInfo {
|
|
||||||
int16_t command; // the command may be different for each subclause, so keep it seperately.
|
|
||||||
uint32_t type; // query/insert type
|
|
||||||
STimeWindow window; // the whole query time window
|
|
||||||
SInterval interval; // tumble time window
|
|
||||||
SSessionWindow sessionWindow; // session time window
|
|
||||||
SStateWindow stateWindow; // state window query
|
|
||||||
SGroupbyExpr groupbyExpr; // groupby tags info
|
|
||||||
SArray * colList; // SArray<SColumn*>
|
|
||||||
SFieldInfo fieldsInfo;
|
|
||||||
SArray** exprList; // SArray<SExprInfo*>
|
|
||||||
SLimit limit;
|
|
||||||
SLimit slimit;
|
|
||||||
STagCond tagCond;
|
|
||||||
SArray * colCond;
|
|
||||||
SArray * order;
|
|
||||||
int16_t numOfTables;
|
|
||||||
int16_t curTableIdx;
|
|
||||||
STableMetaInfo **pTableMetaInfo;
|
|
||||||
struct STSBuf *tsBuf;
|
|
||||||
|
|
||||||
int16_t fillType; // final result fill type
|
|
||||||
int64_t * fillVal; // default value for fill
|
|
||||||
int32_t numOfFillVal; // fill value size
|
|
||||||
|
|
||||||
char * msg; // pointer to the pCmd->payload to keep error message temporarily
|
|
||||||
int64_t clauseLimit; // limit for current sub clause
|
|
||||||
|
|
||||||
int64_t prjOffset; // offset value in the original sql expression, only applied at client side
|
|
||||||
int64_t vgroupLimit; // table limit in case of super table projection query + global order + limit
|
|
||||||
|
|
||||||
int32_t udColumnId; // current user-defined constant output field column id, monotonically decreases from TSDB_UD_COLUMN_INDEX
|
|
||||||
int32_t bufLen;
|
|
||||||
char* buf;
|
|
||||||
SArray *pUdfInfo;
|
|
||||||
|
|
||||||
struct SQueryStmtInfo *sibling; // sibling
|
|
||||||
SMultiFunctionsDesc info;
|
|
||||||
SArray *pDownstream; // SArray<struct SQueryStmtInfo>
|
|
||||||
int32_t havingFieldNum;
|
|
||||||
int32_t exprListLevelIndex;
|
|
||||||
} SQueryStmtInfo;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PAYLOAD_TYPE_KV = 0,
|
|
||||||
PAYLOAD_TYPE_RAW = 1,
|
|
||||||
} EPayloadType;
|
|
||||||
|
|
||||||
typedef struct SVgDataBlocks {
|
|
||||||
SVgroupInfo vg;
|
|
||||||
int32_t numOfTables; // number of tables in current submit block
|
|
||||||
uint32_t size;
|
|
||||||
char *pData; // SMsgDesc + SSubmitReq + SSubmitBlk + ...
|
|
||||||
} SVgDataBlocks;
|
|
||||||
|
|
||||||
typedef struct SVnodeModifOpStmtInfo {
|
|
||||||
int16_t nodeType;
|
|
||||||
SArray* pDataBlocks; // data block for each vgroup, SArray<SVgDataBlocks*>.
|
|
||||||
int8_t schemaAttache; // denote if submit block is built with table schema or not
|
|
||||||
uint8_t payloadType; // EPayloadType. 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert
|
|
||||||
uint32_t insertType; // insert data from [file|sql statement| bound statement]
|
|
||||||
const char* sql; // current sql statement position
|
|
||||||
} SVnodeModifOpStmtInfo;
|
|
||||||
|
|
||||||
typedef struct SDclStmtInfo {
|
|
||||||
int16_t nodeType;
|
|
||||||
int16_t msgType;
|
|
||||||
SEpSet epSet;
|
|
||||||
char* pMsg;
|
|
||||||
int32_t msgLen;
|
|
||||||
void* pExtension; // todo remove it soon
|
|
||||||
} SDclStmtInfo;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*_TD_PARSENODES_H_*/
|
|
|
@ -20,6 +20,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "parsenodes.h"
|
#include "parsenodes.h"
|
||||||
|
|
||||||
typedef struct SParseContext {
|
typedef struct SParseContext {
|
||||||
|
@ -94,6 +96,37 @@ int32_t getNewResColId();
|
||||||
void addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn);
|
void addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn);
|
||||||
SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema);
|
SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "querynodes.h"
|
||||||
|
#include "tmsg.h"
|
||||||
|
|
||||||
|
typedef struct SParseContext {
|
||||||
|
uint64_t requestId;
|
||||||
|
int32_t acctId;
|
||||||
|
const char *db;
|
||||||
|
void *pTransporter;
|
||||||
|
SEpSet mgmtEpSet;
|
||||||
|
const char *pSql; // sql string
|
||||||
|
size_t sqlLen; // length of the sql string
|
||||||
|
char *pMsg; // extended error message if exists to help identifying the problem in sql statement.
|
||||||
|
int32_t msgLen; // max length of the msg
|
||||||
|
struct SCatalog *pCatalog;
|
||||||
|
} SParseContext;
|
||||||
|
|
||||||
|
typedef struct SQuery {
|
||||||
|
bool isCmd;
|
||||||
|
SNode* pRoot;
|
||||||
|
int32_t numOfResCols;
|
||||||
|
SSchema* pResSchema;
|
||||||
|
} SQuery;
|
||||||
|
|
||||||
|
int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery);
|
||||||
|
|
||||||
|
void qDestroyQuery(SQuery* pQueryNode);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
|
@ -207,6 +209,65 @@ void qDestroyQueryDag(SQueryDag* pDag);
|
||||||
char* qDagToString(const SQueryDag* pDag);
|
char* qDagToString(const SQueryDag* pDag);
|
||||||
SQueryDag* qStringToDag(const char* pStr);
|
SQueryDag* qStringToDag(const char* pStr);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "plannodes.h"
|
||||||
|
#include "query.h"
|
||||||
|
|
||||||
|
#define QUERY_TYPE_MERGE 1
|
||||||
|
#define QUERY_TYPE_PARTIAL 2
|
||||||
|
#define QUERY_TYPE_SCAN 3
|
||||||
|
#define QUERY_TYPE_MODIFY 4
|
||||||
|
|
||||||
|
typedef struct SSubplanId {
|
||||||
|
uint64_t queryId;
|
||||||
|
uint64_t templateId;
|
||||||
|
uint64_t subplanId;
|
||||||
|
} SSubplanId;
|
||||||
|
|
||||||
|
typedef struct SSubplan {
|
||||||
|
SSubplanId id; // unique id of the subplan
|
||||||
|
int32_t type; // QUERY_TYPE_MERGE|QUERY_TYPE_PARTIAL|QUERY_TYPE_SCAN|QUERY_TYPE_MODIFY
|
||||||
|
int32_t msgType; // message type for subplan, used to denote the send message type to vnode.
|
||||||
|
int32_t level; // the execution level of current subplan, starting from 0 in a top-down manner.
|
||||||
|
SQueryNodeAddr execNode; // for the scan/modify subplan, the optional execution node
|
||||||
|
SArray* pChildren; // the datasource subplan,from which to fetch the result
|
||||||
|
SArray* pParents; // the data destination subplan, get data from current subplan
|
||||||
|
SPhysiNode* pNode; // physical plan of current subplan
|
||||||
|
SDataSinkNode* pDataSink; // data of the subplan flow into the datasink
|
||||||
|
} SSubplan;
|
||||||
|
|
||||||
|
typedef struct SQueryPlan {
|
||||||
|
uint64_t queryId;
|
||||||
|
int32_t numOfSubplans;
|
||||||
|
SArray* pSubplans; // SArray*<SArray*<SSubplan*>>. The execution level of subplan, starting from 0.
|
||||||
|
} SQueryPlan;
|
||||||
|
|
||||||
|
typedef struct SPlanContext {
|
||||||
|
uint64_t queryId;
|
||||||
|
SNode* pAstRoot;
|
||||||
|
} SPlanContext;
|
||||||
|
|
||||||
|
// Create the physical plan for the query, according to the AST.
|
||||||
|
int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan);
|
||||||
|
|
||||||
|
// Set datasource of this subplan, multiple calls may be made to a subplan.
|
||||||
|
// @subplan subplan to be schedule
|
||||||
|
// @templateId templateId of a group of datasource subplans of this @subplan
|
||||||
|
// @ep one execution location of this group of datasource subplans
|
||||||
|
void qSetSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource);
|
||||||
|
|
||||||
|
// Convert to subplan to string for the scheduler to send to the executor
|
||||||
|
int32_t qSubPlanToString(const SSubplan* subplan, char** str, int32_t* len);
|
||||||
|
int32_t qStringToSubplan(const char* str, SSubplan** subplan);
|
||||||
|
|
||||||
|
char* qQueryPlanToString(const SQueryPlan* pPlan);
|
||||||
|
SQueryPlan* qStringToQueryPlan(const char* pStr);
|
||||||
|
|
||||||
|
void qDestroyQueryPlan(SQueryPlan* pPlan);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(INCLUDE_AS_ENUM) // enum define mode
|
|
||||||
#undef OP_ENUM_MACRO
|
|
||||||
#define OP_ENUM_MACRO(op) OP_##op,
|
|
||||||
#elif defined(INCLUDE_AS_NAME) // comment define mode
|
|
||||||
#undef OP_ENUM_MACRO
|
|
||||||
#define OP_ENUM_MACRO(op) #op,
|
|
||||||
#else
|
|
||||||
#error To use this include file, first define either INCLUDE_AS_ENUM or INCLUDE_AS_NAME
|
|
||||||
#endif
|
|
||||||
|
|
||||||
OP_ENUM_MACRO(StreamScan)
|
|
||||||
OP_ENUM_MACRO(TableScan)
|
|
||||||
OP_ENUM_MACRO(TableSeqScan)
|
|
||||||
OP_ENUM_MACRO(TagScan)
|
|
||||||
OP_ENUM_MACRO(SystemTableScan)
|
|
||||||
OP_ENUM_MACRO(StreamBlockScan)
|
|
||||||
OP_ENUM_MACRO(Aggregate)
|
|
||||||
OP_ENUM_MACRO(Project)
|
|
||||||
// OP_ENUM_MACRO(Groupby)
|
|
||||||
OP_ENUM_MACRO(Limit)
|
|
||||||
OP_ENUM_MACRO(SLimit)
|
|
||||||
OP_ENUM_MACRO(TimeWindow)
|
|
||||||
OP_ENUM_MACRO(SessionWindow)
|
|
||||||
OP_ENUM_MACRO(StateWindow)
|
|
||||||
OP_ENUM_MACRO(Fill)
|
|
||||||
OP_ENUM_MACRO(MultiTableAggregate)
|
|
||||||
OP_ENUM_MACRO(MultiTableTimeInterval)
|
|
||||||
OP_ENUM_MACRO(Filter)
|
|
||||||
OP_ENUM_MACRO(Distinct)
|
|
||||||
OP_ENUM_MACRO(Join)
|
|
||||||
OP_ENUM_MACRO(AllTimeWindow)
|
|
||||||
OP_ENUM_MACRO(AllMultiTableTimeInterval)
|
|
||||||
OP_ENUM_MACRO(Order)
|
|
||||||
OP_ENUM_MACRO(Exchange)
|
|
||||||
|
|
||||||
//OP_ENUM_MACRO(TableScan)
|
|
|
@ -72,7 +72,7 @@ int32_t schedulerInit(SSchedulerCfg *cfg);
|
||||||
* @param nodeList Qnode/Vnode address list, element is SQueryNodeAddr
|
* @param nodeList Qnode/Vnode address list, element is SQueryNodeAddr
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, struct SSchJob** pJob, const char* sql, SQueryResult *pRes);
|
int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryPlan* pDag, struct SSchJob** pJob, const char* sql, SQueryResult *pRes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the query job, generated according to the query physical plan.
|
* Process the query job, generated according to the query physical plan.
|
||||||
|
@ -80,7 +80,7 @@ int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, str
|
||||||
* @param pNodeList Qnode/Vnode address list, element is SQueryNodeAddr
|
* @param pNodeList Qnode/Vnode address list, element is SQueryNodeAddr
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryDag* pDag, const char* sql, struct SSchJob** pJob);
|
int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryPlan* pDag, const char* sql, struct SSchJob** pJob);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch query result from the remote query executor
|
* Fetch query result from the remote query executor
|
||||||
|
@ -112,7 +112,7 @@ void schedulerDestroy(void);
|
||||||
* @param pTasks SArray**<STaskInfo>
|
* @param pTasks SArray**<STaskInfo>
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int32_t schedulerConvertDagToTaskList(SQueryDag* pDag, SArray **pTasks);
|
int32_t schedulerConvertDagToTaskList(SQueryPlan* pDag, SArray **pTasks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* make one task info's multiple copies
|
* make one task info's multiple copies
|
||||||
|
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
taos
|
taos
|
||||||
INTERFACE api
|
INTERFACE api
|
||||||
PRIVATE os util common transport parser planner catalog scheduler function qcom
|
PRIVATE os util common transport nodes parser planner catalog scheduler function qcom
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${BUILD_TEST})
|
if(${BUILD_TEST})
|
||||||
|
|
|
@ -172,7 +172,7 @@ typedef struct SRequestSendRecvBody {
|
||||||
SShowReqInfo showInfo; // todo this attribute will be removed after the query framework being completed.
|
SShowReqInfo showInfo; // todo this attribute will be removed after the query framework being completed.
|
||||||
SDataBuf requestMsg;
|
SDataBuf requestMsg;
|
||||||
struct SSchJob* pQueryJob; // query job, created according to sql query DAG.
|
struct SSchJob* pQueryJob; // query job, created according to sql query DAG.
|
||||||
struct SQueryDag* pDag; // the query dag, generated according to the sql statement.
|
struct SQueryPlan* pDag; // the query dag, generated according to the sql statement.
|
||||||
SReqResultInfo resInfo;
|
SReqResultInfo resInfo;
|
||||||
} SRequestSendRecvBody;
|
} SRequestSendRecvBody;
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ void setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32_t
|
||||||
|
|
||||||
int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj** pRequest);
|
int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj** pRequest);
|
||||||
|
|
||||||
int32_t parseSql(SRequestObj* pRequest, SQueryNode** pQuery);
|
int32_t parseSql(SRequestObj* pRequest, SQuery** pQuery);
|
||||||
|
|
||||||
// --- heartbeat
|
// --- heartbeat
|
||||||
// global, called by mgmt
|
// global, called by mgmt
|
||||||
|
|
|
@ -184,7 +184,7 @@ static void doDestroyRequest(void *p) {
|
||||||
tfree(pRequest->pInfo);
|
tfree(pRequest->pInfo);
|
||||||
|
|
||||||
doFreeReqResultInfo(&pRequest->body.resInfo);
|
doFreeReqResultInfo(&pRequest->body.resInfo);
|
||||||
qDestroyQueryDag(pRequest->body.pDag);
|
qDestroyQueryPlan(pRequest->body.pDag);
|
||||||
|
|
||||||
if (pRequest->body.showInfo.pArray != NULL) {
|
if (pRequest->body.showInfo.pArray != NULL) {
|
||||||
taosArrayDestroy(pRequest->body.showInfo.pArray);
|
taosArrayDestroy(pRequest->body.showInfo.pArray);
|
||||||
|
|
|
@ -139,7 +139,7 @@ int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj*
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t parseSql(SRequestObj* pRequest, SQueryNode** pQuery) {
|
int32_t parseSql(SRequestObj* pRequest, SQuery** pQuery) {
|
||||||
STscObj* pTscObj = pRequest->pTscObj;
|
STscObj* pTscObj = pRequest->pTscObj;
|
||||||
|
|
||||||
SParseContext cxt = {
|
SParseContext cxt = {
|
||||||
|
@ -161,54 +161,57 @@ int32_t parseSql(SRequestObj* pRequest, SQueryNode** pQuery) {
|
||||||
}
|
}
|
||||||
|
|
||||||
code = qParseQuerySql(&cxt, pQuery);
|
code = qParseQuerySql(&cxt, pQuery);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
setResSchemaInfo(&pRequest->body.resInfo, (*pQuery)->pResSchema, (*pQuery)->numOfResCols);
|
||||||
|
}
|
||||||
|
|
||||||
tfree(cxt.db);
|
tfree(cxt.db);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t execDdlQuery(SRequestObj* pRequest, SQueryNode* pQuery) {
|
int32_t execDdlQuery(SRequestObj* pRequest, SQuery* pQuery) {
|
||||||
SDclStmtInfo* pDcl = (SDclStmtInfo*)pQuery;
|
// SDclStmtInfo* pDcl = (SDclStmtInfo*)pQuery;
|
||||||
pRequest->type = pDcl->msgType;
|
// pRequest->type = pDcl->msgType;
|
||||||
pRequest->body.requestMsg = (SDataBuf){.pData = pDcl->pMsg, .len = pDcl->msgLen, .handle = NULL};
|
// pRequest->body.requestMsg = (SDataBuf){.pData = pDcl->pMsg, .len = pDcl->msgLen, .handle = NULL};
|
||||||
|
|
||||||
STscObj* pTscObj = pRequest->pTscObj;
|
// STscObj* pTscObj = pRequest->pTscObj;
|
||||||
SMsgSendInfo* pSendMsg = buildMsgInfoImpl(pRequest);
|
// SMsgSendInfo* pSendMsg = buildMsgInfoImpl(pRequest);
|
||||||
|
|
||||||
int64_t transporterId = 0;
|
// int64_t transporterId = 0;
|
||||||
if (pDcl->msgType == TDMT_VND_CREATE_TABLE || pDcl->msgType == TDMT_VND_SHOW_TABLES) {
|
// if (pDcl->msgType == TDMT_VND_CREATE_TABLE || pDcl->msgType == TDMT_VND_SHOW_TABLES) {
|
||||||
if (pDcl->msgType == TDMT_VND_SHOW_TABLES) {
|
// if (pDcl->msgType == TDMT_VND_SHOW_TABLES) {
|
||||||
SShowReqInfo* pShowReqInfo = &pRequest->body.showInfo;
|
// SShowReqInfo* pShowReqInfo = &pRequest->body.showInfo;
|
||||||
if (pShowReqInfo->pArray == NULL) {
|
// if (pShowReqInfo->pArray == NULL) {
|
||||||
pShowReqInfo->currentIndex = 0; // set the first vnode/ then iterate the next vnode
|
// pShowReqInfo->currentIndex = 0; // set the first vnode/ then iterate the next vnode
|
||||||
pShowReqInfo->pArray = pDcl->pExtension;
|
// pShowReqInfo->pArray = pDcl->pExtension;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pDcl->epSet, &transporterId, pSendMsg);
|
// asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pDcl->epSet, &transporterId, pSendMsg);
|
||||||
} else {
|
// } else {
|
||||||
asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pDcl->epSet, &transporterId, pSendMsg);
|
// asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pDcl->epSet, &transporterId, pSendMsg);
|
||||||
}
|
// }
|
||||||
|
|
||||||
tsem_wait(&pRequest->body.rspSem);
|
// tsem_wait(&pRequest->body.rspSem);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t getPlan(SRequestObj* pRequest, SQueryNode* pQueryNode, SQueryDag** pDag, SArray* pNodeList) {
|
int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pDag, SArray* pNodeList) {
|
||||||
pRequest->type = pQueryNode->type;
|
// pRequest->type = pQuery->type;
|
||||||
|
|
||||||
SSchema* pSchema = NULL;
|
// SSchema* pSchema = NULL;
|
||||||
int32_t numOfCols = 0;
|
// int32_t numOfCols = 0;
|
||||||
int32_t code = qCreateQueryDag(pQueryNode, pDag, &pSchema, &numOfCols, pNodeList, pRequest->requestId);
|
// int32_t code = qCreateQueryDag(pQuery, pDag, &pSchema, &numOfCols, pNodeList, pRequest->requestId);
|
||||||
if (code != 0) {
|
// if (code != 0) {
|
||||||
return code;
|
// return code;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (pQueryNode->type == TSDB_SQL_SELECT) {
|
// if (pQuery->type == TSDB_SQL_SELECT) {
|
||||||
setResSchemaInfo(&pRequest->body.resInfo, pSchema, numOfCols);
|
// setResSchemaInfo(&pRequest->body.resInfo, pSchema, numOfCols);
|
||||||
pRequest->type = TDMT_VND_QUERY;
|
// pRequest->type = TDMT_VND_QUERY;
|
||||||
}
|
// }
|
||||||
|
|
||||||
tfree(pSchema);
|
// tfree(pSchema);
|
||||||
return code;
|
// return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols) {
|
void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols) {
|
||||||
|
@ -224,7 +227,7 @@ void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t scheduleQuery(SRequestObj* pRequest, SQueryDag* pDag, SArray* pNodeList) {
|
int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) {
|
||||||
void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter;
|
void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter;
|
||||||
if (TSDB_SQL_INSERT == pRequest->type || TSDB_SQL_CREATE_TABLE == pRequest->type) {
|
if (TSDB_SQL_INSERT == pRequest->type || TSDB_SQL_CREATE_TABLE == pRequest->type) {
|
||||||
SQueryResult res = {.code = 0, .numOfRows = 0, .msgSize = ERROR_MSG_BUF_DEFAULT_SIZE, .msg = pRequest->msgBuf};
|
SQueryResult res = {.code = 0, .numOfRows = 0, .msgSize = ERROR_MSG_BUF_DEFAULT_SIZE, .msg = pRequest->msgBuf};
|
||||||
|
@ -254,24 +257,24 @@ TAOS_RES* taos_query_l(TAOS* taos, const char* sql, int sqlLen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SRequestObj* pRequest = NULL;
|
SRequestObj* pRequest = NULL;
|
||||||
SQueryNode* pQueryNode = NULL;
|
SQuery* pQuery;
|
||||||
SArray* pNodeList = taosArrayInit(4, sizeof(struct SQueryNodeAddr));
|
SArray* pNodeList = taosArrayInit(4, sizeof(struct SQueryNodeAddr));
|
||||||
|
|
||||||
terrno = TSDB_CODE_SUCCESS;
|
terrno = TSDB_CODE_SUCCESS;
|
||||||
CHECK_CODE_GOTO(buildRequest(pTscObj, sql, sqlLen, &pRequest), _return);
|
CHECK_CODE_GOTO(buildRequest(pTscObj, sql, sqlLen, &pRequest), _return);
|
||||||
CHECK_CODE_GOTO(parseSql(pRequest, &pQueryNode), _return);
|
CHECK_CODE_GOTO(parseSql(pRequest, &pQuery), _return);
|
||||||
|
|
||||||
if (qIsDdlQuery(pQueryNode)) {
|
if (pQuery->isCmd) {
|
||||||
CHECK_CODE_GOTO(execDdlQuery(pRequest, pQueryNode), _return);
|
CHECK_CODE_GOTO(execDdlQuery(pRequest, pQuery), _return);
|
||||||
} else {
|
} else {
|
||||||
CHECK_CODE_GOTO(getPlan(pRequest, pQueryNode, &pRequest->body.pDag, pNodeList), _return);
|
CHECK_CODE_GOTO(getPlan(pRequest, pQuery, &pRequest->body.pDag, pNodeList), _return);
|
||||||
CHECK_CODE_GOTO(scheduleQuery(pRequest, pRequest->body.pDag, pNodeList), _return);
|
CHECK_CODE_GOTO(scheduleQuery(pRequest, pRequest->body.pDag, pNodeList), _return);
|
||||||
pRequest->code = terrno;
|
pRequest->code = terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
_return:
|
_return:
|
||||||
taosArrayDestroy(pNodeList);
|
taosArrayDestroy(pNodeList);
|
||||||
qDestroyQuery(pQueryNode);
|
qDestroyQuery(pQuery);
|
||||||
if (NULL != pRequest && TSDB_CODE_SUCCESS != terrno) {
|
if (NULL != pRequest && TSDB_CODE_SUCCESS != terrno) {
|
||||||
pRequest->code = terrno;
|
pRequest->code = terrno;
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,7 +424,7 @@ SArray* tmqGetConnInfo(SClientHbKey connKey, void* param) {
|
||||||
TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, int sqlLen) {
|
TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, int sqlLen) {
|
||||||
STscObj* pTscObj = (STscObj*)taos;
|
STscObj* pTscObj = (STscObj*)taos;
|
||||||
SRequestObj* pRequest = NULL;
|
SRequestObj* pRequest = NULL;
|
||||||
SQueryNode* pQueryNode = NULL;
|
SQuery* pQueryNode = NULL;
|
||||||
char* pStr = NULL;
|
char* pStr = NULL;
|
||||||
|
|
||||||
terrno = TSDB_CODE_SUCCESS;
|
terrno = TSDB_CODE_SUCCESS;
|
||||||
|
@ -447,7 +447,7 @@ TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, i
|
||||||
}
|
}
|
||||||
|
|
||||||
tscDebug("start to create topic, %s", topicName);
|
tscDebug("start to create topic, %s", topicName);
|
||||||
|
#if 0
|
||||||
CHECK_CODE_GOTO(buildRequest(pTscObj, sql, sqlLen, &pRequest), _return);
|
CHECK_CODE_GOTO(buildRequest(pTscObj, sql, sqlLen, &pRequest), _return);
|
||||||
CHECK_CODE_GOTO(parseSql(pRequest, &pQueryNode), _return);
|
CHECK_CODE_GOTO(parseSql(pRequest, &pQueryNode), _return);
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, i
|
||||||
asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo);
|
asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo);
|
||||||
|
|
||||||
tsem_wait(&pRequest->body.rspSem);
|
tsem_wait(&pRequest->body.rspSem);
|
||||||
|
#endif
|
||||||
_return:
|
_return:
|
||||||
qDestroyQuery(pQueryNode);
|
qDestroyQuery(pQueryNode);
|
||||||
/*if (sendInfo != NULL) {*/
|
/*if (sendInfo != NULL) {*/
|
||||||
|
|
|
@ -760,9 +760,9 @@ static int32_t mndProcessDoRebalanceMsg(SMnodeMsg *pMsg) {
|
||||||
static int32_t mndInitUnassignedVg(SMnode *pMnode, const SMqTopicObj *pTopic, SMqSubscribeObj *pSub) {
|
static int32_t mndInitUnassignedVg(SMnode *pMnode, const SMqTopicObj *pTopic, SMqSubscribeObj *pSub) {
|
||||||
SSdb *pSdb = pMnode->pSdb;
|
SSdb *pSdb = pMnode->pSdb;
|
||||||
SVgObj *pVgroup = NULL;
|
SVgObj *pVgroup = NULL;
|
||||||
SQueryDag *pDag = qStringToDag(pTopic->physicalPlan);
|
SQueryPlan *pPlan = qStringToQueryPlan(pTopic->physicalPlan);
|
||||||
SArray *pArray = NULL;
|
SArray *pArray = NULL;
|
||||||
SArray *inner = taosArrayGet(pDag->pSubplans, 0);
|
SArray *inner = taosArrayGet(pPlan->pSubplans, 0);
|
||||||
SSubplan *plan = taosArrayGetP(inner, 0);
|
SSubplan *plan = taosArrayGetP(inner, 0);
|
||||||
SArray *unassignedVg = pSub->unassignedVg;
|
SArray *unassignedVg = pSub->unassignedVg;
|
||||||
|
|
||||||
|
@ -779,7 +779,7 @@ static int32_t mndInitUnassignedVg(SMnode *pMnode, const SMqTopicObj *pTopic, SM
|
||||||
plan->execNode.nodeId = pVgroup->vgId;
|
plan->execNode.nodeId = pVgroup->vgId;
|
||||||
plan->execNode.epset = mndGetVgroupEpset(pMnode, pVgroup);
|
plan->execNode.epset = mndGetVgroupEpset(pMnode, pVgroup);
|
||||||
|
|
||||||
if (schedulerConvertDagToTaskList(pDag, &pArray) < 0) {
|
if (schedulerConvertDagToTaskList(pPlan, &pArray) < 0) {
|
||||||
terrno = TSDB_CODE_MND_UNSUPPORTED_TOPIC;
|
terrno = TSDB_CODE_MND_UNSUPPORTED_TOPIC;
|
||||||
mError("unsupport topic: %s, sql: %s", pTopic->name, pTopic->sql);
|
mError("unsupport topic: %s, sql: %s", pTopic->name, pTopic->sql);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "dataSinkMgt.h"
|
#include "dataSinkMgt.h"
|
||||||
|
#include "plannodes.h"
|
||||||
|
|
||||||
struct SDataSink;
|
struct SDataSink;
|
||||||
struct SDataSinkHandle;
|
struct SDataSinkHandle;
|
||||||
|
@ -45,7 +46,7 @@ typedef struct SDataSinkHandle {
|
||||||
FDestroyDataSinker fDestroy;
|
FDestroyDataSinker fDestroy;
|
||||||
} SDataSinkHandle;
|
} SDataSinkHandle;
|
||||||
|
|
||||||
int32_t createDataDispatcher(SDataSinkManager* pManager, const struct SDataSink* pDataSink, DataSinkHandle* pHandle);
|
int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ typedef struct SDataCacheEntry {
|
||||||
typedef struct SDataDispatchHandle {
|
typedef struct SDataDispatchHandle {
|
||||||
SDataSinkHandle sink;
|
SDataSinkHandle sink;
|
||||||
SDataSinkManager* pManager;
|
SDataSinkManager* pManager;
|
||||||
SDataBlockSchema schema;
|
SDataBlockDescNode schema;
|
||||||
STaosQueue* pDataBlocks;
|
STaosQueue* pDataBlocks;
|
||||||
SDataDispatchBuf nextOutput;
|
SDataDispatchBuf nextOutput;
|
||||||
int32_t status;
|
int32_t status;
|
||||||
|
@ -48,12 +48,13 @@ typedef struct SDataDispatchHandle {
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
} SDataDispatchHandle;
|
} SDataDispatchHandle;
|
||||||
|
|
||||||
static bool needCompress(const SSDataBlock* pData, const SDataBlockSchema* pSchema) {
|
static bool needCompress(const SSDataBlock* pData, const SDataBlockDescNode* pSchema) {
|
||||||
if (tsCompressColData < 0 || 0 == pData->info.rows) {
|
if (tsCompressColData < 0 || 0 == pData->info.rows) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t col = 0; col < pSchema->numOfCols; ++col) {
|
int32_t numOfCols = LIST_LENGTH(pSchema->pSlots);
|
||||||
|
for (int32_t col = 0; col < numOfCols; ++col) {
|
||||||
SColumnInfoData* pColRes = taosArrayGet(pData->pDataBlock, col);
|
SColumnInfoData* pColRes = taosArrayGet(pData->pDataBlock, col);
|
||||||
int32_t colSize = pColRes->info.bytes * pData->info.rows;
|
int32_t colSize = pColRes->info.bytes * pData->info.rows;
|
||||||
if (NEEDTO_COMPRESS_QUERY(colSize)) {
|
if (NEEDTO_COMPRESS_QUERY(colSize)) {
|
||||||
|
@ -70,13 +71,14 @@ static int32_t compressColData(SColumnInfoData *pColRes, int32_t numOfRows, char
|
||||||
pColRes->pData, colSize, numOfRows, data, colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0);
|
pColRes->pData, colSize, numOfRows, data, colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyData(const SInputData* pInput, const SDataBlockSchema* pSchema, char* data, int8_t compressed, int32_t *compLen) {
|
static void copyData(const SInputData* pInput, const SDataBlockDescNode* pSchema, char* data, int8_t compressed, int32_t *compLen) {
|
||||||
|
int32_t numOfCols = LIST_LENGTH(pSchema->pSlots);
|
||||||
int32_t *compSizes = (int32_t*)data;
|
int32_t *compSizes = (int32_t*)data;
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
data += pSchema->numOfCols * sizeof(int32_t);
|
data += numOfCols * sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t col = 0; col < pSchema->numOfCols; ++col) {
|
for (int32_t col = 0; col < numOfCols; ++col) {
|
||||||
SColumnInfoData* pColRes = taosArrayGet(pInput->pData->pDataBlock, col);
|
SColumnInfoData* pColRes = taosArrayGet(pInput->pData->pDataBlock, col);
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
compSizes[col] = compressColData(pColRes, pInput->pData->info.rows, data, compressed);
|
compSizes[col] = compressColData(pColRes, pInput->pData->info.rows, data, compressed);
|
||||||
|
@ -224,7 +226,7 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) {
|
||||||
pthread_mutex_destroy(&pDispatcher->mutex);
|
pthread_mutex_destroy(&pDispatcher->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSink* pDataSink, DataSinkHandle* pHandle) {
|
int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle) {
|
||||||
SDataDispatchHandle* dispatcher = calloc(1, sizeof(SDataDispatchHandle));
|
SDataDispatchHandle* dispatcher = calloc(1, sizeof(SDataDispatchHandle));
|
||||||
if (NULL == dispatcher) {
|
if (NULL == dispatcher) {
|
||||||
terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
@ -236,7 +238,7 @@ int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSink* pDataS
|
||||||
dispatcher->sink.fGetData = getDataBlock;
|
dispatcher->sink.fGetData = getDataBlock;
|
||||||
dispatcher->sink.fDestroy = destroyDataSinker;
|
dispatcher->sink.fDestroy = destroyDataSinker;
|
||||||
dispatcher->pManager = pManager;
|
dispatcher->pManager = pManager;
|
||||||
dispatcher->schema = pDataSink->schema;
|
dispatcher->schema = pDataSink->inputDataBlockDesc;
|
||||||
dispatcher->status = DS_BUF_EMPTY;
|
dispatcher->status = DS_BUF_EMPTY;
|
||||||
dispatcher->queryEnd = false;
|
dispatcher->queryEnd = false;
|
||||||
dispatcher->pDataBlocks = taosOpenQueue();
|
dispatcher->pDataBlocks = taosOpenQueue();
|
||||||
|
|
|
@ -25,8 +25,8 @@ int32_t dsDataSinkMgtInit(SDataSinkMgtCfg *cfg) {
|
||||||
pthread_mutex_init(&gDataSinkManager.mutex, NULL);
|
pthread_mutex_init(&gDataSinkManager.mutex, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t dsCreateDataSinker(const struct SDataSink *pDataSink, DataSinkHandle* pHandle) {
|
int32_t dsCreateDataSinker(const SDataSinkNode *pDataSink, DataSinkHandle* pHandle) {
|
||||||
if (DSINK_Dispatch == pDataSink->info.type) {
|
if (QUERY_NODE_DSINK_DISPATCH == nodeType(pDataSink)) {
|
||||||
return createDataDispatcher(&gDataSinkManager, pDataSink, pHandle);
|
return createDataDispatcher(&gDataSinkManager, pDataSink, pHandle);
|
||||||
}
|
}
|
||||||
return TSDB_CODE_FAILED;
|
return TSDB_CODE_FAILED;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, char* id) {
|
static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, char* id) {
|
||||||
ASSERT(pOperator != NULL);
|
ASSERT(pOperator != NULL);
|
||||||
if (pOperator->operatorType != OP_StreamScan) {
|
if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
|
||||||
if (pOperator->numOfDownstream == 0) {
|
if (pOperator->numOfDownstream == 0) {
|
||||||
qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id);
|
qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id);
|
||||||
return TSDB_CODE_QRY_APP_ERROR;
|
return TSDB_CODE_QRY_APP_ERROR;
|
||||||
|
|
|
@ -5285,7 +5285,7 @@ SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray*
|
||||||
tsem_init(&pInfo->ready, 0, 0);
|
tsem_init(&pInfo->ready, 0, 0);
|
||||||
|
|
||||||
pOperator->name = "ExchangeOperator";
|
pOperator->name = "ExchangeOperator";
|
||||||
pOperator->operatorType = OP_Exchange;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_EXCHANGE;
|
||||||
pOperator->blockingOptr = false;
|
pOperator->blockingOptr = false;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -5365,7 +5365,7 @@ SOperatorInfo* createTableScanOperatorInfo(void* pTsdbReadHandle, int32_t order,
|
||||||
pInfo->scanFlag = MAIN_SCAN;
|
pInfo->scanFlag = MAIN_SCAN;
|
||||||
|
|
||||||
pOperator->name = "TableScanOperator";
|
pOperator->name = "TableScanOperator";
|
||||||
pOperator->operatorType = OP_TableScan;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN;
|
||||||
pOperator->blockingOptr = false;
|
pOperator->blockingOptr = false;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -5389,7 +5389,7 @@ SOperatorInfo* createTableSeqScanOperatorInfo(void* pTsdbReadHandle, STaskRuntim
|
||||||
|
|
||||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
pOperator->name = "TableSeqScanOperator";
|
pOperator->name = "TableSeqScanOperator";
|
||||||
pOperator->operatorType = OP_TableSeqScan;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN;
|
||||||
pOperator->blockingOptr = false;
|
pOperator->blockingOptr = false;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -5452,7 +5452,7 @@ SOperatorInfo* createStreamScanOperatorInfo(void *streamReadHandle, SArray* pExp
|
||||||
pInfo->readerHandle = streamReadHandle;
|
pInfo->readerHandle = streamReadHandle;
|
||||||
|
|
||||||
pOperator->name = "StreamBlockScanOperator";
|
pOperator->name = "StreamBlockScanOperator";
|
||||||
pOperator->operatorType = OP_StreamScan;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN;
|
||||||
pOperator->blockingOptr = false;
|
pOperator->blockingOptr = false;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -6236,7 +6236,7 @@ SOperatorInfo *createOrderOperatorInfo(SOperatorInfo* downstream, SArray* pExprI
|
||||||
}
|
}
|
||||||
|
|
||||||
pOperator->name = "Order";
|
pOperator->name = "Order";
|
||||||
pOperator->operatorType = OP_Order;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SORT;
|
||||||
pOperator->blockingOptr = true;
|
pOperator->blockingOptr = true;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -7193,6 +7193,21 @@ static int32_t initAggInfo(SAggOperatorInfo* pInfo, SArray* pExprInfo, int32_t n
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void assignExprInfo(SExprInfo* dst, const SExprInfo* src) {
|
||||||
|
assert(dst != NULL && src != NULL);
|
||||||
|
|
||||||
|
*dst = *src;
|
||||||
|
|
||||||
|
dst->pExpr = exprdup(src->pExpr);
|
||||||
|
dst->base.pColumns = calloc(src->base.numOfCols, sizeof(SColumn));
|
||||||
|
memcpy(dst->base.pColumns, src->base.pColumns, sizeof(SColumn) * src->base.numOfCols);
|
||||||
|
|
||||||
|
memset(dst->base.param, 0, sizeof(SVariant) * tListLen(dst->base.param));
|
||||||
|
for (int32_t j = 0; j < src->base.numOfParams; ++j) {
|
||||||
|
taosVariantAssign(&dst->base.param[j], &src->base.param[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static SExprInfo* exprArrayDup(SArray* pExprInfo) {
|
static SExprInfo* exprArrayDup(SArray* pExprInfo) {
|
||||||
size_t numOfOutput = taosArrayGetSize(pExprInfo);
|
size_t numOfOutput = taosArrayGetSize(pExprInfo);
|
||||||
SExprInfo* p = calloc(numOfOutput, sizeof(SExprInfo));
|
SExprInfo* p = calloc(numOfOutput, sizeof(SExprInfo));
|
||||||
|
@ -7215,7 +7230,7 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pE
|
||||||
|
|
||||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
pOperator->name = "TableAggregate";
|
pOperator->name = "TableAggregate";
|
||||||
pOperator->operatorType = OP_Aggregate;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_AGG;
|
||||||
pOperator->blockingOptr = true;
|
pOperator->blockingOptr = true;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -7316,7 +7331,7 @@ SOperatorInfo* createMultiTableAggOperatorInfo(SOperatorInfo* downstream, SArray
|
||||||
|
|
||||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
pOperator->name = "MultiTableAggregate";
|
pOperator->name = "MultiTableAggregate";
|
||||||
pOperator->operatorType = OP_MultiTableAggregate;
|
// pOperator->operatorType = OP_MultiTableAggregate;
|
||||||
pOperator->blockingOptr = true;
|
pOperator->blockingOptr = true;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -7690,7 +7705,7 @@ SOperatorInfo* createSLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorI
|
||||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
|
|
||||||
pOperator->name = "SLimitOperator";
|
pOperator->name = "SLimitOperator";
|
||||||
pOperator->operatorType = OP_SLimit;
|
// pOperator->operatorType = OP_SLimit;
|
||||||
pOperator->blockingOptr = false;
|
pOperator->blockingOptr = false;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
// pOperator->exec = doSLimit;
|
// pOperator->exec = doSLimit;
|
||||||
|
@ -7846,7 +7861,7 @@ SOperatorInfo* createTagScanOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SExprInfo
|
||||||
|
|
||||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
pOperator->name = "SeqTableTagScan";
|
pOperator->name = "SeqTableTagScan";
|
||||||
pOperator->operatorType = OP_TagScan;
|
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN;
|
||||||
pOperator->blockingOptr = false;
|
pOperator->blockingOptr = false;
|
||||||
pOperator->status = OP_IN_EXECUTING;
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
|
@ -8164,25 +8179,25 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId) {
|
||||||
return pTaskInfo;
|
return pTaskInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tsdbReaderT doCreateDataReader(STableScanPhyNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId);
|
static tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId);
|
||||||
|
|
||||||
static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo, uint64_t queryId, uint64_t taskId);
|
static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo, uint64_t queryId, uint64_t taskId);
|
||||||
|
|
||||||
SOperatorInfo* doCreateOperatorTreeNode(SPhyNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId, STableGroupInfo* pTableGroupInfo) {
|
SOperatorInfo* doCreateOperatorTreeNode(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId, STableGroupInfo* pTableGroupInfo) {
|
||||||
if (pPhyNode->pChildren == NULL || taosArrayGetSize(pPhyNode->pChildren) == 0) {
|
if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) {
|
||||||
if (pPhyNode->info.type == OP_TableScan) {
|
if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pPhyNode)) {
|
||||||
SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode;
|
SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode;
|
||||||
|
|
||||||
size_t numOfCols = taosArrayGetSize(pPhyNode->pTargets);
|
size_t numOfCols = LIST_LENGTH(pScanPhyNode->pScanCols);
|
||||||
tsdbReaderT pDataReader = doCreateDataReader((STableScanPhyNode*) pPhyNode, pHandle, (uint64_t) queryId, taskId);
|
tsdbReaderT pDataReader = doCreateDataReader((STableScanPhysiNode*) pPhyNode, pHandle, (uint64_t) queryId, taskId);
|
||||||
|
|
||||||
int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId);
|
int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId);
|
||||||
return createTableScanOperatorInfo(pDataReader, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pScanPhyNode->reverse, pTaskInfo);
|
return createTableScanOperatorInfo(pDataReader, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pScanPhyNode->reverse, pTaskInfo);
|
||||||
} else if (pPhyNode->info.type == OP_Exchange) {
|
} else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == nodeType(pPhyNode)) {
|
||||||
SExchangePhyNode* pEx = (SExchangePhyNode*) pPhyNode;
|
// SExchangePhysiNode* pEx = (SExchangePhysiNode*) pPhyNode;
|
||||||
return createExchangeOperatorInfo(pEx->pSrcEndPoints, pEx->node.pTargets, pTaskInfo);
|
// return createExchangeOperatorInfo(pEx->pSrcEndPoints, pEx->node.pTargets, pTaskInfo);
|
||||||
} else if (pPhyNode->info.type == OP_StreamScan) {
|
} else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == nodeType(pPhyNode)) {
|
||||||
SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode; // simple child table.
|
SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode; // simple child table.
|
||||||
STableGroupInfo groupInfo = {0};
|
STableGroupInfo groupInfo = {0};
|
||||||
|
|
||||||
int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, &groupInfo, queryId, taskId);
|
int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, &groupInfo, queryId, taskId);
|
||||||
|
@ -8198,58 +8213,58 @@ SOperatorInfo* doCreateOperatorTreeNode(SPhyNode* pPhyNode, SExecTaskInfo* pTask
|
||||||
taosArrayPush(idList, &pkeyInfo->uid);
|
taosArrayPush(idList, &pkeyInfo->uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pPhyNode->pTargets, idList, pTaskInfo);
|
// SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pScanPhyNode->pScanCols, idList, pTaskInfo);
|
||||||
taosArrayDestroy(idList);
|
// taosArrayDestroy(idList);
|
||||||
|
|
||||||
//TODO destroy groupInfo
|
// //TODO destroy groupInfo
|
||||||
return pOperator;
|
// return pOperator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pPhyNode->info.type == OP_Aggregate) {
|
if (QUERY_NODE_PHYSICAL_PLAN_AGG == nodeType(pPhyNode)) {
|
||||||
size_t size = taosArrayGetSize(pPhyNode->pChildren);
|
size_t size = LIST_LENGTH(pPhyNode->pChildren);
|
||||||
assert(size == 1);
|
assert(size == 1);
|
||||||
|
|
||||||
// TODO single table agg
|
// TODO single table agg
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
for (int32_t i = 0; i < size; ++i) {
|
||||||
SPhyNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i);
|
SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i);
|
||||||
SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo);
|
SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo);
|
||||||
return createAggregateOperatorInfo(op, pPhyNode->pTargets, pTaskInfo, pTableGroupInfo);
|
// return createAggregateOperatorInfo(op, pPhyNode->pTargets, pTaskInfo, pTableGroupInfo);
|
||||||
}
|
}
|
||||||
} else if (pPhyNode->info.type == OP_MultiTableAggregate) {
|
} /*else if (pPhyNode->info.type == OP_MultiTableAggregate) {
|
||||||
size_t size = taosArrayGetSize(pPhyNode->pChildren);
|
size_t size = taosArrayGetSize(pPhyNode->pChildren);
|
||||||
assert(size == 1);
|
assert(size == 1);
|
||||||
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
for (int32_t i = 0; i < size; ++i) {
|
||||||
SPhyNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i);
|
SPhysiNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i);
|
||||||
SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo);
|
SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo);
|
||||||
return createMultiTableAggOperatorInfo(op, pPhyNode->pTargets, pTaskInfo, pTableGroupInfo);
|
return createMultiTableAggOperatorInfo(op, pPhyNode->pTargets, pTaskInfo, pTableGroupInfo);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static tsdbReaderT createDataReaderImpl(STableScanPhyNode* pTableScanNode, STableGroupInfo* pGroupInfo, void* readHandle, uint64_t queryId, uint64_t taskId) {
|
static tsdbReaderT createDataReaderImpl(STableScanPhysiNode* pTableScanNode, STableGroupInfo* pGroupInfo, void* readHandle, uint64_t queryId, uint64_t taskId) {
|
||||||
STsdbQueryCond cond = {.loadExternalRows = false};
|
STsdbQueryCond cond = {.loadExternalRows = false};
|
||||||
|
|
||||||
cond.order = pTableScanNode->scan.order;
|
cond.order = pTableScanNode->scan.order;
|
||||||
cond.numOfCols = taosArrayGetSize(pTableScanNode->scan.node.pTargets);
|
cond.numOfCols = LIST_LENGTH(pTableScanNode->scan.pScanCols);
|
||||||
cond.colList = calloc(cond.numOfCols, sizeof(SColumnInfo));
|
cond.colList = calloc(cond.numOfCols, sizeof(SColumnInfo));
|
||||||
if (cond.colList == NULL) {
|
if (cond.colList == NULL) {
|
||||||
terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cond.twindow = pTableScanNode->window;
|
cond.twindow = pTableScanNode->scanRange;
|
||||||
cond.type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
|
cond.type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
|
||||||
|
|
||||||
for (int32_t i = 0; i < cond.numOfCols; ++i) {
|
for (int32_t i = 0; i < cond.numOfCols; ++i) {
|
||||||
SExprInfo* pExprInfo = taosArrayGetP(pTableScanNode->scan.node.pTargets, i);
|
// SExprInfo* pExprInfo = taosArrayGetP(pTableScanNode->scan.node.pTargets, i);
|
||||||
assert(pExprInfo->pExpr->nodeType == TEXPR_COL_NODE);
|
// assert(pExprInfo->pExpr->nodeType == TEXPR_COL_NODE);
|
||||||
|
|
||||||
SSchema* pSchema = pExprInfo->pExpr->pSchema;
|
// SSchema* pSchema = pExprInfo->pExpr->pSchema;
|
||||||
cond.colList[i].type = pSchema->type;
|
// cond.colList[i].type = pSchema->type;
|
||||||
cond.colList[i].bytes = pSchema->bytes;
|
// cond.colList[i].bytes = pSchema->bytes;
|
||||||
cond.colList[i].colId = pSchema->colId;
|
// cond.colList[i].colId = pSchema->colId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tsdbQueryTables(readHandle, &cond, pGroupInfo, queryId, taskId);
|
return tsdbQueryTables(readHandle, &cond, pGroupInfo, queryId, taskId);
|
||||||
|
@ -8266,7 +8281,7 @@ static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tsdbReaderT doCreateDataReader(STableScanPhyNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId) {
|
static tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId) {
|
||||||
STableGroupInfo groupInfo = {0};
|
STableGroupInfo groupInfo = {0};
|
||||||
|
|
||||||
uint64_t uid = pTableScanNode->scan.uid;
|
uint64_t uid = pTableScanNode->scan.uid;
|
||||||
|
|
|
@ -1,369 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_ASTGENERATOR_H
|
|
||||||
#define TDENGINE_ASTGENERATOR_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ttoken.h"
|
|
||||||
#include "tvariant.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
#define ParseTOKENTYPE SToken
|
|
||||||
|
|
||||||
#define NON_ARITHMEIC_EXPR 0
|
|
||||||
#define NORMAL_ARITHMETIC 1
|
|
||||||
#define AGG_ARIGHTMEIC 2
|
|
||||||
|
|
||||||
enum SQL_NODE_TYPE {
|
|
||||||
SQL_NODE_TABLE_COLUMN= 1,
|
|
||||||
SQL_NODE_SQLFUNCTION = 2,
|
|
||||||
SQL_NODE_VALUE = 3,
|
|
||||||
SQL_NODE_EXPR = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SQL_FROM_NODE_TYPE {
|
|
||||||
SQL_FROM_NODE_SUBQUERY = 1,
|
|
||||||
SQL_FROM_NODE_TABLES = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SQL_UNION_TYPE {
|
|
||||||
SQL_TYPE_UNIONALL = 1,
|
|
||||||
SQL_TYPE_UNION = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern char tTokenTypeSwitcher[13];
|
|
||||||
|
|
||||||
#define toTSDBType(x) \
|
|
||||||
do { \
|
|
||||||
if ((x) >= tListLen(tTokenTypeSwitcher)) { \
|
|
||||||
(x) = TSDB_DATA_TYPE_BINARY; \
|
|
||||||
} else { \
|
|
||||||
(x) = tTokenTypeSwitcher[(x)]; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TPARSER_HAS_TOKEN(_t) ((_t).n > 0)
|
|
||||||
#define TPARSER_SET_NONE_TOKEN(_t) ((_t).n = 0)
|
|
||||||
|
|
||||||
typedef struct SListItem {
|
|
||||||
SVariant pVar;
|
|
||||||
uint8_t sortOrder;
|
|
||||||
} SListItem;
|
|
||||||
|
|
||||||
typedef struct SIntervalVal {
|
|
||||||
int32_t token;
|
|
||||||
SToken interval;
|
|
||||||
SToken offset;
|
|
||||||
} SIntervalVal;
|
|
||||||
|
|
||||||
typedef struct SSessionWindowVal {
|
|
||||||
SToken col;
|
|
||||||
SToken gap;
|
|
||||||
} SSessionWindowVal;
|
|
||||||
|
|
||||||
typedef struct SWindowStateVal {
|
|
||||||
SToken col;
|
|
||||||
} SWindowStateVal;
|
|
||||||
|
|
||||||
struct SRelationInfo;
|
|
||||||
|
|
||||||
typedef struct SSqlNode {
|
|
||||||
struct SRelationInfo *from; // from clause SArray<SSqlNode>
|
|
||||||
struct SArray *pSelNodeList; // select clause
|
|
||||||
struct tSqlExpr *pWhere; // where clause [optional]
|
|
||||||
SArray *pGroupby; // groupby clause, only for tags[optional], SArray<SListItem>
|
|
||||||
SArray *pSortOrder; // orderby [optional], SArray<SListItem>
|
|
||||||
SArray *fillType; // fill type[optional], SArray<SListItem>
|
|
||||||
SIntervalVal interval; // (interval, interval_offset) [optional]
|
|
||||||
SSessionWindowVal sessionVal; // session window [optional]
|
|
||||||
SWindowStateVal windowstateVal; // window_state(col) [optional]
|
|
||||||
SToken sliding; // sliding window [optional]
|
|
||||||
SLimit limit; // limit offset [optional]
|
|
||||||
SLimit slimit; // group limit offset [optional]
|
|
||||||
SToken sqlstr; // sql string in select clause
|
|
||||||
struct tSqlExpr *pHaving; // having clause [optional]
|
|
||||||
} SSqlNode;
|
|
||||||
|
|
||||||
typedef struct SSubclause {
|
|
||||||
int32_t unionType;
|
|
||||||
SArray *node;
|
|
||||||
} SSubclause;
|
|
||||||
|
|
||||||
typedef struct SRelElement {
|
|
||||||
union {
|
|
||||||
SToken tableName;
|
|
||||||
SSubclause *pSubquery;
|
|
||||||
};
|
|
||||||
|
|
||||||
SToken aliasName;
|
|
||||||
} SRelElement;
|
|
||||||
|
|
||||||
typedef struct SRelationInfo {
|
|
||||||
int32_t type; // nested query|table name list
|
|
||||||
SArray *list; // SArray<SRelElement>
|
|
||||||
} SRelationInfo;
|
|
||||||
|
|
||||||
typedef struct SCreatedTableInfo {
|
|
||||||
SToken name; // table name token
|
|
||||||
SToken stbName; // super table name token , for using clause
|
|
||||||
SArray *pTagNames; // create by using super table, tag name
|
|
||||||
SArray *pTagVals; // create by using super table, tag value. SArray<SToken>
|
|
||||||
char *fullname; // table full name
|
|
||||||
int8_t igExist; // ignore if exists
|
|
||||||
} SCreatedTableInfo;
|
|
||||||
|
|
||||||
typedef struct SCreateTableSql {
|
|
||||||
SToken name; // table name, create table [name] xxx
|
|
||||||
int8_t type; // create normal table/from super table/ stream
|
|
||||||
bool existCheck;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
SArray *pTagColumns; // SArray<SField>
|
|
||||||
SArray *pColumns; // SArray<SField>
|
|
||||||
} colInfo;
|
|
||||||
|
|
||||||
SArray *childTableInfo; // SArray<SCreatedTableInfo>
|
|
||||||
SSqlNode *pSelect;
|
|
||||||
} SCreateTableSql;
|
|
||||||
|
|
||||||
typedef struct SAlterTableInfo {
|
|
||||||
SToken name;
|
|
||||||
int16_t tableType;
|
|
||||||
int16_t type;
|
|
||||||
STagData tagData;
|
|
||||||
SArray *pAddColumns; // SArray<SField>
|
|
||||||
SArray *varList; // set t=val or: change src dst, SArray<SListItem>
|
|
||||||
} SAlterTableInfo;
|
|
||||||
|
|
||||||
typedef struct SCreateDbInfo {
|
|
||||||
SToken dbname;
|
|
||||||
int32_t replica;
|
|
||||||
int32_t cacheBlockSize;
|
|
||||||
int32_t numOfVgroups;
|
|
||||||
int32_t numOfBlocks;
|
|
||||||
int32_t daysPerFile;
|
|
||||||
int32_t minRowsPerBlock;
|
|
||||||
int32_t maxRowsPerBlock;
|
|
||||||
int32_t fsyncPeriod;
|
|
||||||
int64_t commitTime;
|
|
||||||
int32_t walLevel;
|
|
||||||
int32_t quorum;
|
|
||||||
int32_t compressionLevel;
|
|
||||||
SToken precision;
|
|
||||||
bool ignoreExists;
|
|
||||||
int8_t update;
|
|
||||||
int8_t cachelast;
|
|
||||||
SArray *keep;
|
|
||||||
int8_t streamMode;
|
|
||||||
} SCreateDbInfo;
|
|
||||||
|
|
||||||
typedef struct SCreateFuncInfo {
|
|
||||||
SToken name;
|
|
||||||
SToken path;
|
|
||||||
int32_t type;
|
|
||||||
int32_t bufSize;
|
|
||||||
SField output;
|
|
||||||
} SCreateFuncInfo;
|
|
||||||
|
|
||||||
typedef struct SCreateAcctInfo {
|
|
||||||
int32_t maxUsers;
|
|
||||||
int32_t maxDbs;
|
|
||||||
int32_t maxTimeSeries;
|
|
||||||
int32_t maxStreams;
|
|
||||||
int32_t maxPointsPerSecond;
|
|
||||||
int64_t maxStorage;
|
|
||||||
int64_t maxQueryTime;
|
|
||||||
int32_t maxConnections;
|
|
||||||
SToken stat;
|
|
||||||
} SCreateAcctInfo;
|
|
||||||
|
|
||||||
typedef struct SShowInfo {
|
|
||||||
uint8_t showType;
|
|
||||||
SToken prefix;
|
|
||||||
SToken pattern;
|
|
||||||
} SShowInfo;
|
|
||||||
|
|
||||||
typedef struct SUserInfo {
|
|
||||||
SToken user;
|
|
||||||
SToken passwd;
|
|
||||||
SToken privilege;
|
|
||||||
int16_t type;
|
|
||||||
} SUserInfo;
|
|
||||||
|
|
||||||
typedef struct SMiscInfo {
|
|
||||||
SArray *a; // SArray<SToken>
|
|
||||||
bool existsCheck;
|
|
||||||
int16_t dbType;
|
|
||||||
int16_t tableType;
|
|
||||||
SUserInfo user;
|
|
||||||
union {
|
|
||||||
SCreateDbInfo dbOpt;
|
|
||||||
SCreateAcctInfo acctOpt;
|
|
||||||
SCreateFuncInfo funcOpt;
|
|
||||||
SShowInfo showOpt;
|
|
||||||
SToken id;
|
|
||||||
};
|
|
||||||
} SMiscInfo;
|
|
||||||
|
|
||||||
typedef struct SSqlInfo {
|
|
||||||
int32_t type;
|
|
||||||
bool valid;
|
|
||||||
SSubclause sub;
|
|
||||||
char msg[256];
|
|
||||||
SArray *funcs;
|
|
||||||
union {
|
|
||||||
SCreateTableSql *pCreateTableInfo;
|
|
||||||
SAlterTableInfo *pAlterInfo;
|
|
||||||
SMiscInfo *pMiscInfo;
|
|
||||||
};
|
|
||||||
} SSqlInfo;
|
|
||||||
|
|
||||||
typedef struct tSqlExpr {
|
|
||||||
uint16_t type; // sql node type
|
|
||||||
uint32_t tokenId; // TK_LE: less than(binary expr)
|
|
||||||
|
|
||||||
// The complete string of the function(col, param), and the function name is kept in exprToken
|
|
||||||
struct {
|
|
||||||
SToken operand;
|
|
||||||
struct SArray *paramList; // function parameters list
|
|
||||||
} Expr;
|
|
||||||
|
|
||||||
SToken columnName; // table column info
|
|
||||||
SVariant value; // the use input value
|
|
||||||
SToken exprToken; // original sql expr string or function name of sql function
|
|
||||||
struct tSqlExpr *pLeft; // the left child
|
|
||||||
struct tSqlExpr *pRight; // the right child
|
|
||||||
} tSqlExpr;
|
|
||||||
|
|
||||||
// used in select clause. select <SArray> from xxx
|
|
||||||
typedef struct tSqlExprItem {
|
|
||||||
tSqlExpr *pNode; // The list of expressions
|
|
||||||
int32_t functionId;
|
|
||||||
char *aliasName; // alias name, null-terminated string
|
|
||||||
bool distinct;
|
|
||||||
} tSqlExprItem;
|
|
||||||
|
|
||||||
SArray *tListItemAppend(SArray *pList, SVariant *pVar, uint8_t sortOrder);
|
|
||||||
SArray *tListItemInsert(SArray *pList, SVariant *pVar, uint8_t sortOrder, int32_t index);
|
|
||||||
SArray *tListItemAppendToken(SArray *pList, SToken *pAliasToken, uint8_t sortOrder);
|
|
||||||
|
|
||||||
SRelationInfo *setTableNameList(SRelationInfo *pRelationInfo, SToken *pName, SToken *pAlias);
|
|
||||||
void * destroyRelationInfo(SRelationInfo *pFromInfo);
|
|
||||||
SRelationInfo *addSubquery(SRelationInfo *pRelationInfo, SSubclause *pSub, SToken *pAlias);
|
|
||||||
|
|
||||||
// sql expr leaf node
|
|
||||||
tSqlExpr *tSqlExprCreateIdValue(SToken *pToken, int32_t optrType);
|
|
||||||
tSqlExpr *tSqlExprCreateFunction(SArray *pParam, SToken *pFuncToken, SToken *endToken, int32_t optType);
|
|
||||||
SArray * tRecordFuncName(SArray *pList, SToken *pToken);
|
|
||||||
|
|
||||||
tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType);
|
|
||||||
tSqlExpr *tSqlExprClone(tSqlExpr *pSrc);
|
|
||||||
void tSqlExprCompact(tSqlExpr **pExpr);
|
|
||||||
bool tSqlExprIsLeaf(tSqlExpr *pExpr);
|
|
||||||
bool tSqlExprIsParentOfLeaf(tSqlExpr *pExpr);
|
|
||||||
void tSqlExprDestroy(tSqlExpr *pExpr);
|
|
||||||
SArray * tSqlExprListAppend(SArray *pList, tSqlExpr *pNode, SToken *pDistinct, SToken *pToken);
|
|
||||||
void tSqlExprListDestroy(SArray *pList);
|
|
||||||
void tSqlExprEvaluate(tSqlExpr* pExpr);
|
|
||||||
|
|
||||||
SSqlNode *tSetQuerySqlNode(SToken *pSelectToken, SArray *pSelNodeList, SRelationInfo *pFrom, tSqlExpr *pWhere,
|
|
||||||
SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *ps,
|
|
||||||
SWindowStateVal *pw, SToken *pSliding, SArray *pFill, SLimit *pLimit, SLimit *pgLimit, tSqlExpr *pHaving);
|
|
||||||
int32_t tSqlExprCompare(tSqlExpr *left, tSqlExpr *right);
|
|
||||||
|
|
||||||
SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SSqlNode *pSelect, int32_t type);
|
|
||||||
|
|
||||||
SAlterTableInfo * tSetAlterTableInfo(SToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableType);
|
|
||||||
SCreatedTableInfo createNewChildTableInfo(SToken *pTableName, SArray *pTagNames, SArray *pTagVals, SToken *pToken,
|
|
||||||
SToken *igExists);
|
|
||||||
/*!
|
|
||||||
* test
|
|
||||||
* @param pSqlNode
|
|
||||||
*/
|
|
||||||
void destroyAllSqlNode(struct SSubclause *pSqlNode);
|
|
||||||
void destroySqlNode(SSqlNode *pSql);
|
|
||||||
void freeCreateTableInfo(void* p);
|
|
||||||
|
|
||||||
SSqlInfo *setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SToken *pTableName, int32_t type);
|
|
||||||
SSubclause* setSubclause(SSubclause* sub, void *pSqlNode);
|
|
||||||
SSubclause* appendSelectClause(SSubclause *sub, int32_t unionType, void *pSubclause);
|
|
||||||
|
|
||||||
void setCreatedTableName(SSqlInfo *pInfo, SToken *pTableNameToken, SToken *pIfNotExists);
|
|
||||||
void* destroyCreateTableSql(SCreateTableSql* pCreate);
|
|
||||||
void setDropFuncInfo(SSqlInfo *pInfo, int32_t type, SToken* pToken);
|
|
||||||
void setCreateFuncInfo(SSqlInfo *pInfo, int32_t type, SToken *pName, SToken *pPath, SField *output, SToken* bufSize, int32_t funcType);
|
|
||||||
|
|
||||||
void destroySqlInfo(SSqlInfo *pInfo);
|
|
||||||
|
|
||||||
void setDCLSqlElems(SSqlInfo *pInfo, int32_t type, int32_t nParams, ...);
|
|
||||||
void setDropDbTableInfo(SSqlInfo *pInfo, int32_t type, SToken* pToken, SToken* existsCheck,int16_t dbType,int16_t tableType);
|
|
||||||
void setShowOptions(SSqlInfo *pInfo, int32_t type, SToken* prefix, SToken* pPatterns);
|
|
||||||
|
|
||||||
void setCreateDbInfo(SSqlInfo *pInfo, int32_t type, SToken *pToken, SCreateDbInfo *pDB, SToken *pIgExists);
|
|
||||||
|
|
||||||
void setCreateAcctSql(SSqlInfo *pInfo, int32_t type, SToken *pName, SToken *pPwd, SCreateAcctInfo *pAcctInfo);
|
|
||||||
void setCreateUserSql(SSqlInfo *pInfo, SToken *pName, SToken *pPasswd);
|
|
||||||
void setKillSql(SSqlInfo *pInfo, int32_t type, SToken *ip);
|
|
||||||
void setAlterUserSql(SSqlInfo *pInfo, int16_t type, SToken *pName, SToken* pPwd, SToken *pPrivilege);
|
|
||||||
|
|
||||||
void setCompactVnodeSql(SSqlInfo *pInfo, int32_t type, SArray *pParam);
|
|
||||||
|
|
||||||
void setDefaultCreateDbOption(SCreateDbInfo *pDBInfo);
|
|
||||||
void setDefaultCreateTopicOption(SCreateDbInfo *pDBInfo);
|
|
||||||
|
|
||||||
// prefix show db.tables;
|
|
||||||
void tSetDbName(SToken *pCpxName, SToken *pDb);
|
|
||||||
|
|
||||||
void tSetColumnInfo(struct SField *pField, SToken *pName, struct SField *pType);
|
|
||||||
void tSetColumnType(struct SField *pField, SToken *type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main parse function.
|
|
||||||
* @param yyp The parser
|
|
||||||
* @param yymajor The major token code number
|
|
||||||
* @param yyminor The value for the token
|
|
||||||
*/
|
|
||||||
void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor, SSqlInfo *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the allocated resources in case of failure.
|
|
||||||
* @param p The parser to be deleted
|
|
||||||
* @param freeProc Function used to reclaim memory
|
|
||||||
*/
|
|
||||||
void ParseFree(void *p, void (*freeProc)(void *));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocated callback function.
|
|
||||||
* @param mallocProc The parser allocator
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void *ParseAlloc(void *(*mallocProc)(size_t));
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param str sql string
|
|
||||||
* @return sql ast
|
|
||||||
*/
|
|
||||||
SSqlInfo doGenerateAST(const char *str);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TDENGINE_ASTGENERATOR_H
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_ASTTOMSG_H
|
|
||||||
#define TDENGINE_ASTTOMSG_H
|
|
||||||
|
|
||||||
#include "parserInt.h"
|
|
||||||
#include "tmsg.h"
|
|
||||||
|
|
||||||
char* buildUserManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen);
|
|
||||||
char* buildAcctManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen);
|
|
||||||
char* buildDropUserMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen);
|
|
||||||
char* buildShowMsg(SShowInfo* pShowInfo, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf);
|
|
||||||
char* buildCreateDbMsg(SCreateDbInfo* pCreateDbInfo, int32_t* outputLen, SParseContext* pCtx, SMsgBuf* pMsgBuf);
|
|
||||||
char* buildCreateStbReq(SCreateTableSql* pCreateTableSql, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf);
|
|
||||||
char* buildDropStableReq(SSqlInfo* pInfo, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf);
|
|
||||||
char* buildCreateDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf);
|
|
||||||
char* buildDropDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf);
|
|
||||||
|
|
||||||
#endif // TDENGINE_ASTTOMSG_H
|
|
|
@ -22,7 +22,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo);
|
int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "querynodes.h"
|
#include "parser.h"
|
||||||
#include "newParser.h"
|
|
||||||
|
|
||||||
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
|
int32_t doParse(SParseContext* pParseCxt, SQuery** pQuery);
|
||||||
int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery);
|
int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery);
|
||||||
|
int32_t parseQuerySql(SParseContext* pCxt, SQuery** pQuery);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_PARSER_INT_H_
|
|
||||||
#define _TD_PARSER_INT_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "catalog.h"
|
|
||||||
#include "tname.h"
|
|
||||||
#include "astGenerator.h"
|
|
||||||
|
|
||||||
struct SSqlNode;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct SInternalField {
|
|
||||||
TAOS_FIELD field;
|
|
||||||
bool visible;
|
|
||||||
SExprInfo *pExpr;
|
|
||||||
} SInternalField;
|
|
||||||
|
|
||||||
typedef struct SMsgBuf {
|
|
||||||
int32_t len;
|
|
||||||
char *buf;
|
|
||||||
} SMsgBuf;
|
|
||||||
|
|
||||||
void clearTableMetaInfo(STableMetaInfo* pTableMetaInfo);
|
|
||||||
|
|
||||||
void clearAllTableMetaInfo(SQueryStmtInfo* pQueryInfo, bool removeMeta, uint64_t id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the sql info, according to the corresponding metadata info from catalog.
|
|
||||||
* @param pCtx
|
|
||||||
* @param pInfo
|
|
||||||
* @param pQueryInfo
|
|
||||||
* @param msgBuf
|
|
||||||
* @param msgBufLen
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t qParserValidateSqlNode(SParseContext *pCtx, SSqlInfo* pInfo, SQueryStmtInfo* pQueryInfo, char* msgBuf, int32_t msgBufLen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* validate the ddl ast, and convert the ast to the corresponding message format
|
|
||||||
* @param pSqlInfo
|
|
||||||
* @param output
|
|
||||||
* @param type
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param pInfo
|
|
||||||
* @param pCtx
|
|
||||||
* @param msgBuf
|
|
||||||
* @param msgBufLen
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
SVnodeModifOpStmtInfo* qParserValidateCreateTbSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate the numeric and timestamp arithmetic expression in the WHERE clause.
|
|
||||||
* @param pNode
|
|
||||||
* @param tsPrecision
|
|
||||||
* @param msg
|
|
||||||
* @param msgBufLen
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, SMsgBuf* pMsgBuf);
|
|
||||||
|
|
||||||
int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf);
|
|
||||||
|
|
||||||
SQueryStmtInfo* createQueryInfo();
|
|
||||||
|
|
||||||
void destroyQueryInfo(SQueryStmtInfo* pQueryInfo);
|
|
||||||
|
|
||||||
int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract request meta info from the sql statement
|
|
||||||
* @param pSqlInfo
|
|
||||||
* @param pMetaInfo
|
|
||||||
* @param msg
|
|
||||||
* @param msgBufLen
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SCatalogReq* pMetaInfo, SParseContext *pCtx, char* msg, int32_t msgBufLen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy the meta data request structure.
|
|
||||||
* @param pMetaInfo
|
|
||||||
*/
|
|
||||||
void qParserCleanupMetaRequestInfo(SCatalogReq* pMetaInfo);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*_TD_PARSER_INT_H_*/
|
|
|
@ -21,54 +21,19 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "query.h"
|
||||||
|
#include "tmsg.h"
|
||||||
#include "ttoken.h"
|
#include "ttoken.h"
|
||||||
#include "parserInt.h"
|
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_SUPER_TABLE(metaInfo) \
|
typedef struct SMsgBuf {
|
||||||
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_SUPER_TABLE))
|
int32_t len;
|
||||||
|
char *buf;
|
||||||
#define UTIL_TABLE_IS_CHILD_TABLE(metaInfo) \
|
} SMsgBuf;
|
||||||
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE))
|
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo) \
|
|
||||||
(!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo)))
|
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \
|
|
||||||
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE))
|
|
||||||
|
|
||||||
TAOS_FIELD createField(const SSchema* pSchema);
|
|
||||||
void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema);
|
|
||||||
SColumn createColumn(uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema);
|
|
||||||
|
|
||||||
SInternalField* insertFieldInfo(SFieldInfo* pFieldInfo, int32_t index, SSchema* field);
|
|
||||||
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 parserValidateNameToken(SToken* pToken);
|
|
||||||
|
|
||||||
int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg);
|
int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg);
|
||||||
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr);
|
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr);
|
||||||
|
|
||||||
STableMetaInfo* addEmptyMetaInfo(SQueryStmtInfo* pQueryInfo);
|
int32_t parserValidateIdToken(SToken* pToken);
|
||||||
|
|
||||||
void columnListCopyAll(SArray* dst, const SArray* src);
|
|
||||||
|
|
||||||
SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag);
|
|
||||||
SColumn* insertPrimaryTsColumn(SArray* pColumnList, const char* colName, uint64_t tableUid);
|
|
||||||
|
|
||||||
void cleanupTagCond(STagCond* pTagCond);
|
|
||||||
void cleanupColumnCond(SArray** pCond);
|
|
||||||
|
|
||||||
uint32_t convertRelationalOperator(SToken *pToken);
|
|
||||||
int32_t getExprFunctionId(SExprInfo *pExprInfo);
|
|
||||||
|
|
||||||
STableMeta* tableMetaDup(const STableMeta* pTableMeta);
|
|
||||||
|
|
||||||
bool isDclSqlStatement(SSqlInfo* pSqlInfo);
|
|
||||||
bool isDdlSqlStatement(SSqlInfo* pSqlInfo);
|
|
||||||
bool isDqlSqlStatement(SSqlInfo* pSqlInfo);
|
|
||||||
|
|
||||||
typedef struct SKvParam {
|
typedef struct SKvParam {
|
||||||
SKVRowBuilder *builder;
|
SKVRowBuilder *builder;
|
||||||
|
@ -78,10 +43,12 @@ typedef struct SKvParam {
|
||||||
|
|
||||||
int32_t KvRowAppend(const void *value, int32_t len, void *param);
|
int32_t KvRowAppend(const void *value, int32_t len, void *param);
|
||||||
|
|
||||||
typedef int32_t (*_row_append_fn_t)(const void *value, int32_t len, void *param);
|
STableMeta* tableMetaDup(const STableMeta* pTableMeta);
|
||||||
int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf);
|
SSchema *getTableColumnSchema(const STableMeta *pTableMeta);
|
||||||
|
SSchema *getTableTagSchema(const STableMeta* pTableMeta);
|
||||||
int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf);
|
int32_t getNumOfColumns(const STableMeta* pTableMeta);
|
||||||
|
int32_t getNumOfTags(const STableMeta* pTableMeta);
|
||||||
|
STableComInfo getTableInfo(const STableMeta* pTableMeta);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_QUERYINFOUTIL_H
|
|
||||||
#define TDENGINE_QUERYINFOUTIL_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include "parserInt.h"
|
|
||||||
|
|
||||||
SSchema* getTbnameColumnSchema();
|
|
||||||
|
|
||||||
int32_t getNumOfColumns(const STableMeta* pTableMeta);
|
|
||||||
int32_t getNumOfTags(const STableMeta* pTableMeta);
|
|
||||||
SSchema *getTableColumnSchema(const STableMeta *pTableMeta);
|
|
||||||
SSchema *getTableTagSchema(const STableMeta* pTableMeta);
|
|
||||||
|
|
||||||
SArray *getCurrentExprList(SQueryStmtInfo* pQueryInfo);
|
|
||||||
size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo);
|
|
||||||
|
|
||||||
void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level);
|
|
||||||
void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize);
|
|
||||||
|
|
||||||
SExprInfo* getExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index);
|
|
||||||
|
|
||||||
void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes);
|
|
||||||
|
|
||||||
void cleanupFieldInfo(SFieldInfo* pFieldInfo);
|
|
||||||
|
|
||||||
STableComInfo getTableInfo(const STableMeta* pTableMeta);
|
|
||||||
SArray *extractFunctionList(SArray* pExprInfoList);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TDENGINE_QUERYINFOUTIL_H
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,520 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "astGenerator.h"
|
|
||||||
#include "parserInt.h"
|
|
||||||
#include "parserUtil.h"
|
|
||||||
|
|
||||||
char* buildUserManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen) {
|
|
||||||
SCreateUserReq createReq = {0};
|
|
||||||
|
|
||||||
SUserInfo* pUser = &pInfo->pMiscInfo->user;
|
|
||||||
strncpy(createReq.user, pUser->user.z, pUser->user.n);
|
|
||||||
createReq.createType = pUser->type;
|
|
||||||
createReq.superUser = (int8_t)pUser->type;
|
|
||||||
|
|
||||||
if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) {
|
|
||||||
// pMsg->privilege = (char)pCmd->count;
|
|
||||||
} else {
|
|
||||||
strncpy(createReq.pass, pUser->passwd.z, pUser->passwd.n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSCreateUserReq(NULL, 0, &createReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSCreateUserReq(pReq, tlen, &createReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildAcctManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen) {
|
|
||||||
SCreateAcctReq createReq = {0};
|
|
||||||
|
|
||||||
SToken* pName = &pInfo->pMiscInfo->user.user;
|
|
||||||
SToken* pPwd = &pInfo->pMiscInfo->user.passwd;
|
|
||||||
|
|
||||||
strncpy(createReq.user, pName->z, pName->n);
|
|
||||||
strncpy(createReq.pass, pPwd->z, pPwd->n);
|
|
||||||
|
|
||||||
SCreateAcctInfo* pAcctOpt = &pInfo->pMiscInfo->acctOpt;
|
|
||||||
|
|
||||||
createReq.maxUsers = pAcctOpt->maxUsers;
|
|
||||||
createReq.maxDbs = pAcctOpt->maxDbs;
|
|
||||||
createReq.maxTimeSeries = pAcctOpt->maxTimeSeries;
|
|
||||||
createReq.maxStreams = pAcctOpt->maxStreams;
|
|
||||||
createReq.maxStorage = pAcctOpt->maxStorage;
|
|
||||||
|
|
||||||
if (pAcctOpt->stat.n == 0) {
|
|
||||||
createReq.accessState = -1;
|
|
||||||
} else {
|
|
||||||
if (pAcctOpt->stat.z[0] == 'r' && pAcctOpt->stat.n == 1) {
|
|
||||||
createReq.accessState = TSDB_VN_READ_ACCCESS;
|
|
||||||
} else if (pAcctOpt->stat.z[0] == 'w' && pAcctOpt->stat.n == 1) {
|
|
||||||
createReq.accessState = TSDB_VN_WRITE_ACCCESS;
|
|
||||||
} else if (strncmp(pAcctOpt->stat.z, "all", 3) == 0 && pAcctOpt->stat.n == 3) {
|
|
||||||
createReq.accessState = TSDB_VN_ALL_ACCCESS;
|
|
||||||
} else if (strncmp(pAcctOpt->stat.z, "no", 2) == 0 && pAcctOpt->stat.n == 2) {
|
|
||||||
createReq.accessState = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSCreateAcctReq(NULL, 0, &createReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSCreateAcctReq(pReq, tlen, &createReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildDropUserMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgBufLen) {
|
|
||||||
SDropUserReq dropReq = {0};
|
|
||||||
|
|
||||||
SToken* pName = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
|
||||||
if (pName->n >= TSDB_USER_LEN) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(dropReq.user, pName->z, pName->n);
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSDropUserReq(NULL, 0, &dropReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSDropUserReq(pReq, tlen, &dropReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildShowMsg(SShowInfo* pShowInfo, int32_t* outputLen, SParseContext* pCtx, SMsgBuf* pMsgBuf) {
|
|
||||||
SShowReq showReq = {.type = pShowInfo->showType};
|
|
||||||
|
|
||||||
if (pShowInfo->showType != TSDB_MGMT_TABLE_VNODES) {
|
|
||||||
SToken* pPattern = &pShowInfo->pattern;
|
|
||||||
if (pPattern->type > 0) { // only show tables support wildcard query
|
|
||||||
showReq.payloadLen = pPattern->n;
|
|
||||||
showReq.payload = malloc(showReq.payloadLen);
|
|
||||||
strncpy(showReq.payload, pPattern->z, pPattern->n);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SToken* pEpAddr = &pShowInfo->prefix;
|
|
||||||
assert(pEpAddr->n > 0 && pEpAddr->type > 0);
|
|
||||||
showReq.payloadLen = pEpAddr->n;
|
|
||||||
showReq.payload = malloc(showReq.payloadLen);
|
|
||||||
strncpy(showReq.payload, pEpAddr->z, pEpAddr->n);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pShowInfo->showType == TSDB_MGMT_TABLE_STB || pShowInfo->showType == TSDB_MGMT_TABLE_VGROUP) {
|
|
||||||
SName n = {0};
|
|
||||||
|
|
||||||
if (pShowInfo->prefix.n > 0) {
|
|
||||||
if (pShowInfo->prefix.n >= TSDB_DB_FNAME_LEN) {
|
|
||||||
terrno = buildInvalidOperationMsg(pMsgBuf, "prefix name is too long");
|
|
||||||
tFreeSShowReq(&showReq);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
tNameSetDbName(&n, pCtx->acctId, pShowInfo->prefix.z, pShowInfo->prefix.n);
|
|
||||||
} else if (pCtx->db == NULL || strlen(pCtx->db) == 0) {
|
|
||||||
terrno = buildInvalidOperationMsg(pMsgBuf, "database is not specified");
|
|
||||||
tFreeSShowReq(&showReq);
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
tNameSetDbName(&n, pCtx->acctId, pCtx->db, strlen(pCtx->db));
|
|
||||||
}
|
|
||||||
|
|
||||||
tNameGetFullDbName(&n, showReq.db);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSShowReq(NULL, 0, &showReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSShowReq(pReq, tlen, &showReq);
|
|
||||||
tFreeSShowReq(&showReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t setKeepOption(SCreateDbReq* pMsg, const SCreateDbInfo* pCreateDb, SMsgBuf* pMsgBuf) {
|
|
||||||
const char* msg1 = "invalid number of keep options";
|
|
||||||
const char* msg2 = "invalid keep value";
|
|
||||||
const char* msg3 = "invalid keep value, should be keep0 <= keep1 <= keep2";
|
|
||||||
|
|
||||||
pMsg->daysToKeep0 = -1;
|
|
||||||
pMsg->daysToKeep1 = -1;
|
|
||||||
pMsg->daysToKeep2 = -1;
|
|
||||||
|
|
||||||
SArray* pKeep = pCreateDb->keep;
|
|
||||||
if (pKeep != NULL) {
|
|
||||||
size_t s = taosArrayGetSize(pKeep);
|
|
||||||
#ifdef _STORAGE
|
|
||||||
if (s >= 4 || s <= 0) {
|
|
||||||
#else
|
|
||||||
if (s != 1) {
|
|
||||||
#endif
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tListI* p0 = taosArrayGet(pKeep, 0);
|
|
||||||
// tVariantListItem* p1 = (s > 1) ? taosArrayGet(pKeep, 1) : p0;
|
|
||||||
// tVariantListItem* p2 = (s > 2) ? taosArrayGet(pKeep, 2) : p1;
|
|
||||||
//
|
|
||||||
// if ((int32_t)p0->pVar.i64 <= 0 || (int32_t)p1->pVar.i64 <= 0 || (int32_t)p2->pVar.i64 <= 0) {
|
|
||||||
// return buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
// }
|
|
||||||
// if (!(((int32_t)p0->pVar.i64 <= (int32_t)p1->pVar.i64) && ((int32_t)p1->pVar.i64 <= (int32_t)p2->pVar.i64))) {
|
|
||||||
// return buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pMsg->daysToKeep0 = htonl((int32_t)p0->pVar.i64);
|
|
||||||
// pMsg->daysToKeep1 = htonl((int32_t)p1->pVar.i64);
|
|
||||||
// pMsg->daysToKeep2 = htonl((int32_t)p2->pVar.i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t setTimePrecision(SCreateDbReq* pMsg, const SCreateDbInfo* pCreateDbInfo, SMsgBuf* pMsgBuf) {
|
|
||||||
const char* msg = "invalid time precision";
|
|
||||||
|
|
||||||
pMsg->precision = TSDB_TIME_PRECISION_MILLI; // millisecond by default
|
|
||||||
|
|
||||||
SToken* pToken = (SToken*)&pCreateDbInfo->precision;
|
|
||||||
if (pToken->n > 0) {
|
|
||||||
pToken->n = strdequote(pToken->z);
|
|
||||||
|
|
||||||
if (strncmp(pToken->z, TSDB_TIME_PRECISION_MILLI_STR, pToken->n) == 0 &&
|
|
||||||
strlen(TSDB_TIME_PRECISION_MILLI_STR) == pToken->n) {
|
|
||||||
// time precision for this db: million second
|
|
||||||
pMsg->precision = TSDB_TIME_PRECISION_MILLI;
|
|
||||||
} else if (strncmp(pToken->z, TSDB_TIME_PRECISION_MICRO_STR, pToken->n) == 0 &&
|
|
||||||
strlen(TSDB_TIME_PRECISION_MICRO_STR) == pToken->n) {
|
|
||||||
pMsg->precision = TSDB_TIME_PRECISION_MICRO;
|
|
||||||
} else if (strncmp(pToken->z, TSDB_TIME_PRECISION_NANO_STR, pToken->n) == 0 &&
|
|
||||||
strlen(TSDB_TIME_PRECISION_NANO_STR) == pToken->n) {
|
|
||||||
pMsg->precision = TSDB_TIME_PRECISION_NANO;
|
|
||||||
} else {
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void doSetDbOptions(SCreateDbReq* pMsg, const SCreateDbInfo* pCreateDb) {
|
|
||||||
pMsg->cacheBlockSize = pCreateDb->cacheBlockSize;
|
|
||||||
pMsg->totalBlocks = pCreateDb->numOfBlocks;
|
|
||||||
pMsg->daysPerFile = pCreateDb->daysPerFile;
|
|
||||||
pMsg->commitTime = (int32_t)pCreateDb->commitTime;
|
|
||||||
pMsg->minRows = pCreateDb->minRowsPerBlock;
|
|
||||||
pMsg->maxRows = pCreateDb->maxRowsPerBlock;
|
|
||||||
pMsg->fsyncPeriod = pCreateDb->fsyncPeriod;
|
|
||||||
pMsg->compression = (int8_t)pCreateDb->compressionLevel;
|
|
||||||
pMsg->walLevel = (char)pCreateDb->walLevel;
|
|
||||||
pMsg->replications = pCreateDb->replica;
|
|
||||||
pMsg->quorum = pCreateDb->quorum;
|
|
||||||
pMsg->ignoreExist = pCreateDb->ignoreExists;
|
|
||||||
pMsg->update = pCreateDb->update;
|
|
||||||
pMsg->cacheLastRow = pCreateDb->cachelast;
|
|
||||||
pMsg->numOfVgroups = pCreateDb->numOfVgroups;
|
|
||||||
pMsg->streamMode = pCreateDb->streamMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t setDbOptions(SCreateDbReq* pCreateDbMsg, const SCreateDbInfo* pCreateDbSql, SMsgBuf* pMsgBuf) {
|
|
||||||
doSetDbOptions(pCreateDbMsg, pCreateDbSql);
|
|
||||||
|
|
||||||
if (setKeepOption(pCreateDbMsg, pCreateDbSql, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setTimePrecision(pCreateDbMsg, pCreateDbSql, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// can only perform the parameters based on the macro definitation
|
|
||||||
static int32_t doCheckDbOptions(SCreateDbReq* pCreate, SMsgBuf* pMsgBuf) {
|
|
||||||
char msg[512] = {0};
|
|
||||||
|
|
||||||
if (pCreate->walLevel != -1 && (pCreate->walLevel < TSDB_MIN_WAL_LEVEL || pCreate->walLevel > TSDB_MAX_WAL_LEVEL)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option walLevel: %d, only 1-2 allowed", pCreate->walLevel);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCreate->replications != -1 &&
|
|
||||||
(pCreate->replications < TSDB_MIN_DB_REPLICA_OPTION || pCreate->replications > TSDB_MAX_DB_REPLICA_OPTION)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option replications: %d valid range: [%d, %d]", pCreate->replications,
|
|
||||||
TSDB_MIN_DB_REPLICA_OPTION, TSDB_MAX_DB_REPLICA_OPTION);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t blocks = pCreate->totalBlocks;
|
|
||||||
if (blocks != -1 && (blocks < TSDB_MIN_TOTAL_BLOCKS || blocks > TSDB_MAX_TOTAL_BLOCKS)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option totalBlocks: %d valid range: [%d, %d]", blocks,
|
|
||||||
TSDB_MIN_TOTAL_BLOCKS, TSDB_MAX_TOTAL_BLOCKS);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCreate->quorum != -1 &&
|
|
||||||
(pCreate->quorum < TSDB_MIN_DB_QUORUM_OPTION || pCreate->quorum > TSDB_MAX_DB_QUORUM_OPTION)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option quorum: %d valid range: [%d, %d]", pCreate->quorum,
|
|
||||||
TSDB_MIN_DB_QUORUM_OPTION, TSDB_MAX_DB_QUORUM_OPTION);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t val = pCreate->daysPerFile;
|
|
||||||
if (val != -1 && (val < TSDB_MIN_DAYS_PER_FILE || val > TSDB_MAX_DAYS_PER_FILE)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option daysPerFile: %d valid range: [%d, %d]", val, TSDB_MIN_DAYS_PER_FILE,
|
|
||||||
TSDB_MAX_DAYS_PER_FILE);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = pCreate->cacheBlockSize;
|
|
||||||
if (val != -1 && (val < TSDB_MIN_CACHE_BLOCK_SIZE || val > TSDB_MAX_CACHE_BLOCK_SIZE)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option cacheBlockSize: %d valid range: [%d, %d]", val,
|
|
||||||
TSDB_MIN_CACHE_BLOCK_SIZE, TSDB_MAX_CACHE_BLOCK_SIZE);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCreate->precision != TSDB_TIME_PRECISION_MILLI && pCreate->precision != TSDB_TIME_PRECISION_MICRO &&
|
|
||||||
pCreate->precision != TSDB_TIME_PRECISION_NANO) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option timePrecision: %d valid value: [%d, %d, %d]", pCreate->precision,
|
|
||||||
TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO, TSDB_TIME_PRECISION_NANO);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = pCreate->commitTime;
|
|
||||||
if (val != -1 && (val < TSDB_MIN_COMMIT_TIME || val > TSDB_MAX_COMMIT_TIME)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option commitTime: %d valid range: [%d, %d]", val, TSDB_MIN_COMMIT_TIME,
|
|
||||||
TSDB_MAX_COMMIT_TIME);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = pCreate->fsyncPeriod;
|
|
||||||
if (val != -1 && (val < TSDB_MIN_FSYNC_PERIOD || val > TSDB_MAX_FSYNC_PERIOD)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option fsyncPeriod: %d valid range: [%d, %d]", val, TSDB_MIN_FSYNC_PERIOD,
|
|
||||||
TSDB_MAX_FSYNC_PERIOD);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCreate->compression != -1 &&
|
|
||||||
(pCreate->compression < TSDB_MIN_COMP_LEVEL || pCreate->compression > TSDB_MAX_COMP_LEVEL)) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid db option compression: %d valid range: [%d, %d]", pCreate->compression,
|
|
||||||
TSDB_MIN_COMP_LEVEL, TSDB_MAX_COMP_LEVEL);
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = pCreate->numOfVgroups;
|
|
||||||
if (val < TSDB_MIN_VNODES_PER_DB || val > TSDB_MAX_VNODES_PER_DB) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid number of vgroups for DB:%d valid range: [%d, %d]", val,
|
|
||||||
TSDB_MIN_VNODES_PER_DB, TSDB_MAX_VNODES_PER_DB);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = pCreate->maxRows;
|
|
||||||
if (val < TSDB_MIN_MAX_ROW_FBLOCK || val > TSDB_MAX_MAX_ROW_FBLOCK) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid number of max rows in file block for DB:%d valid range: [%d, %d]", val,
|
|
||||||
TSDB_MIN_MAX_ROW_FBLOCK, TSDB_MAX_MAX_ROW_FBLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = pCreate->minRows;
|
|
||||||
if (val < TSDB_MIN_MIN_ROW_FBLOCK || val > TSDB_MAX_MIN_ROW_FBLOCK) {
|
|
||||||
snprintf(msg, tListLen(msg), "invalid number of min rows in file block for DB:%d valid range: [%d, %d]", val,
|
|
||||||
TSDB_MIN_MIN_ROW_FBLOCK, TSDB_MAX_MIN_ROW_FBLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildCreateDbMsg(SCreateDbInfo* pCreateDbInfo, int32_t* outputLen, SParseContext* pCtx, SMsgBuf* pMsgBuf) {
|
|
||||||
SCreateDbReq createReq = {0};
|
|
||||||
|
|
||||||
if (setDbOptions(&createReq, pCreateDbInfo, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SName name = {0};
|
|
||||||
int32_t ret = tNameSetDbName(&name, pCtx->acctId, pCreateDbInfo->dbname.z, pCreateDbInfo->dbname.n);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = ret;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tNameGetFullDbName(&name, createReq.db);
|
|
||||||
|
|
||||||
if (doCheckDbOptions(&createReq, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSCreateDbReq(NULL, 0, &createReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSCreateDbReq(pReq, tlen, &createReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildCreateStbReq(SCreateTableSql* pCreateTableSql, int32_t* outputLen, SParseContext* pParseCtx,
|
|
||||||
SMsgBuf* pMsgBuf) {
|
|
||||||
SMCreateStbReq createReq = {0};
|
|
||||||
createReq.igExists = pCreateTableSql->existCheck ? 1 : 0;
|
|
||||||
createReq.pColumns = pCreateTableSql->colInfo.pColumns;
|
|
||||||
createReq.pTags = pCreateTableSql->colInfo.pTagColumns;
|
|
||||||
createReq.numOfColumns = (int32_t)taosArrayGetSize(pCreateTableSql->colInfo.pColumns);
|
|
||||||
createReq.numOfTags = (int32_t)taosArrayGetSize(pCreateTableSql->colInfo.pTagColumns);
|
|
||||||
|
|
||||||
SName n = {0};
|
|
||||||
if (createSName(&n, &pCreateTableSql->name, pParseCtx, pMsgBuf) != 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tNameExtractFullName(&n, createReq.name) != 0) {
|
|
||||||
buildInvalidOperationMsg(pMsgBuf, "invalid table name or database not specified");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSMCreateStbReq(NULL, 0, &createReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSMCreateStbReq(pReq, tlen, &createReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildDropStableReq(SSqlInfo* pInfo, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) {
|
|
||||||
SToken* tableName = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
|
||||||
|
|
||||||
SName name = {0};
|
|
||||||
int32_t code = createSName(&name, tableName, pParseCtx, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = buildInvalidOperationMsg(pMsgBuf, "invalid table name");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMDropStbReq dropReq = {0};
|
|
||||||
code = tNameExtractFullName(&name, dropReq.name);
|
|
||||||
|
|
||||||
assert(code == TSDB_CODE_SUCCESS && name.type == TSDB_TABLE_NAME_T);
|
|
||||||
dropReq.igNotExists = pInfo->pMiscInfo->existsCheck ? 1 : 0;
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSMDropStbReq(NULL, 0, &dropReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSMDropStbReq(pReq, tlen, &dropReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildCreateDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf) {
|
|
||||||
const char* msg1 = "invalid host name (name too long, maximum length 128)";
|
|
||||||
const char* msg2 = "dnode name can not be string";
|
|
||||||
const char* msg3 = "port should be an integer that is less than 65535 and greater than 0";
|
|
||||||
const char* msg4 = "failed prepare create dnode message";
|
|
||||||
|
|
||||||
if (taosArrayGetSize(pInfo->pMiscInfo->a) != 2) {
|
|
||||||
buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SToken* id = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
|
||||||
if (id->type != TK_ID && id->type != TK_IPTOKEN) {
|
|
||||||
buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SToken* port = taosArrayGet(pInfo->pMiscInfo->a, 1);
|
|
||||||
if (port->type != TK_INTEGER) {
|
|
||||||
buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSign = false;
|
|
||||||
int64_t val = 0;
|
|
||||||
|
|
||||||
toInteger(port->z, port->n, 10, &val, &isSign);
|
|
||||||
if (val >= UINT16_MAX || val <= 0) {
|
|
||||||
buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SCreateDnodeReq createReq = {0};
|
|
||||||
|
|
||||||
strncpy(createReq.fqdn, id->z, id->n);
|
|
||||||
createReq.port = val;
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSCreateDnodeReq(NULL, 0, &createReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSCreateDnodeReq(pReq, tlen, &createReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buildDropDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf) {
|
|
||||||
SDropDnodeReq dropReq = {0};
|
|
||||||
|
|
||||||
SToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
|
||||||
|
|
||||||
char* end = NULL;
|
|
||||||
dropReq.dnodeId = strtoll(pzName->z, &end, 10);
|
|
||||||
|
|
||||||
if (end - pzName->z != pzName->n) {
|
|
||||||
buildInvalidOperationMsg(pMsgBuf, "invalid dnode id");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tlen = tSerializeSDropDnodeReq(NULL, 0, &dropReq);
|
|
||||||
void* pReq = malloc(tlen);
|
|
||||||
if (pReq == NULL) {
|
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSerializeSDropDnodeReq(pReq, tlen, &dropReq);
|
|
||||||
*outputLen = tlen;
|
|
||||||
return pReq;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,901 +0,0 @@
|
||||||
#include "tmsg.h"
|
|
||||||
#include "tglobal.h"
|
|
||||||
#include "parserInt.h"
|
|
||||||
#include "ttime.h"
|
|
||||||
#include "astToMsg.h"
|
|
||||||
#include "astGenerator.h"
|
|
||||||
#include "parserUtil.h"
|
|
||||||
#include "queryInfoUtil.h"
|
|
||||||
|
|
||||||
/* 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 setShowInfo(SShowInfo* pShowInfo, SParseContext* pCtx, void** output, int32_t* outputLen,
|
|
||||||
SEpSet* pEpSet, void** pExtension, 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";
|
|
||||||
const char* msg7 = "database not specified";
|
|
||||||
/*
|
|
||||||
* database prefix in pInfo->pMiscInfo->a[0]
|
|
||||||
* wildcard in like clause in pInfo->pMiscInfo->a[1]
|
|
||||||
*/
|
|
||||||
int16_t showType = pShowInfo->showType;
|
|
||||||
if (showType == TSDB_MGMT_TABLE_TABLE) {
|
|
||||||
SArray* array = NULL;
|
|
||||||
SName name = {0};
|
|
||||||
|
|
||||||
if (pCtx->db == NULL && pShowInfo->prefix.n == 0) {
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg7);
|
|
||||||
}
|
|
||||||
|
|
||||||
SVShowTablesReq* pShowReq = calloc(1, sizeof(SVShowTablesReq));
|
|
||||||
if (pShowInfo->prefix.n > 0) {
|
|
||||||
tNameSetDbName(&name, pCtx->acctId, pShowInfo->prefix.z, pShowInfo->prefix.n);
|
|
||||||
} else {
|
|
||||||
tNameSetDbName(&name, pCtx->acctId, pCtx->db, strlen(pCtx->db));
|
|
||||||
}
|
|
||||||
|
|
||||||
char dbFname[TSDB_DB_FNAME_LEN] = {0};
|
|
||||||
tNameGetFullDbName(&name, dbFname);
|
|
||||||
|
|
||||||
int32_t code = catalogGetDBVgInfo(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, dbFname, false, &array);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = code;
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
SVgroupInfo* info = taosArrayGet(array, 0);
|
|
||||||
pShowReq->head.vgId = htonl(info->vgId);
|
|
||||||
*pEpSet = info->epset;
|
|
||||||
|
|
||||||
*outputLen = sizeof(SVShowTablesReq);
|
|
||||||
*output = pShowReq;
|
|
||||||
*pExtension = array;
|
|
||||||
} else {
|
|
||||||
if (showType == TSDB_MGMT_TABLE_STB || 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*pEpSet = pCtx->mgmtEpSet;
|
|
||||||
*output = buildShowMsg(pShowInfo, outputLen, pCtx, pMsgBuf);
|
|
||||||
if (*output == NULL) {
|
|
||||||
return terrno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 && pMsgBuf != NULL);
|
|
||||||
|
|
||||||
const char* msg1 = "first column must be timestamp";
|
|
||||||
const char* msg2 = "illegal number of columns";
|
|
||||||
|
|
||||||
// first column must be timestamp
|
|
||||||
SField* 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, msg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
SField* 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(SCreateTableSql* pCreateTable, SMsgBuf* pMsgBuf) {
|
|
||||||
const char* msg1 = "invalid table name";
|
|
||||||
|
|
||||||
SArray* pFieldList = pCreateTable->colInfo.pColumns;
|
|
||||||
SArray* pTagList = pCreateTable->colInfo.pTagColumns;
|
|
||||||
assert(pFieldList != NULL);
|
|
||||||
|
|
||||||
// if sql specifies db, use it, otherwise use default db
|
|
||||||
SToken* pNameToken = &(pCreateTable->name);
|
|
||||||
|
|
||||||
if (parserValidateIdToken(pNameToken) != 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct SVgroupTablesBatch {
|
|
||||||
SVCreateTbBatchReq req;
|
|
||||||
SVgroupInfo info;
|
|
||||||
} SVgroupTablesBatch;
|
|
||||||
|
|
||||||
static SArray* doSerializeVgroupCreateTableInfo(SHashObj* pVgroupHashmap);
|
|
||||||
|
|
||||||
static int32_t doParseSerializeTagValue(SSchema* pTagSchema, int32_t numOfInputTag, SKVRowBuilder* pKvRowBuilder,
|
|
||||||
SArray* pTagValList, int32_t tsPrecision, SMsgBuf* pMsgBuf) {
|
|
||||||
const char* msg1 = "illegal value or data overflow";
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < numOfInputTag; ++i) {
|
|
||||||
SSchema* pSchema = &pTagSchema[i];
|
|
||||||
|
|
||||||
char* endPtr = NULL;
|
|
||||||
char tmpTokenBuf[TSDB_MAX_TAGS_LEN] = {0};
|
|
||||||
SKvParam param = {.builder = pKvRowBuilder, .schema = pSchema};
|
|
||||||
|
|
||||||
SToken* pItem = taosArrayGet(pTagValList, i);
|
|
||||||
code = parseValueToken(&endPtr, pItem, pSchema, tsPrecision, tmpTokenBuf, KvRowAppend, ¶m, pMsgBuf);
|
|
||||||
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addCreateTbReqIntoVgroup(SHashObj* pVgroupHashmap, const SName* pTableName, SKVRow row, uint64_t suid, SVgroupInfo* pVgInfo) {
|
|
||||||
struct SVCreateTbReq req = {0};
|
|
||||||
req.type = TD_CHILD_TABLE;
|
|
||||||
req.name = strdup(tNameGetTableName(pTableName));
|
|
||||||
req.ctbCfg.suid = suid;
|
|
||||||
req.ctbCfg.pTag = row;
|
|
||||||
|
|
||||||
SVgroupTablesBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId));
|
|
||||||
if (pTableBatch == NULL) {
|
|
||||||
SVgroupTablesBatch tBatch = {0};
|
|
||||||
tBatch.info = *pVgInfo;
|
|
||||||
|
|
||||||
tBatch.req.pArray = taosArrayInit(4, sizeof(struct SVCreateTbReq));
|
|
||||||
taosArrayPush(tBatch.req.pArray, &req);
|
|
||||||
|
|
||||||
taosHashPut(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId), &tBatch, sizeof(tBatch));
|
|
||||||
} else { // add to the correct vgroup
|
|
||||||
assert(pVgInfo->vgId == pTableBatch->info.vgId);
|
|
||||||
taosArrayPush(pTableBatch->req.pArray, &req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyCreateTbReqBatch(SVgroupTablesBatch* pTbBatch) {
|
|
||||||
size_t size = taosArrayGetSize(pTbBatch->req.pArray);
|
|
||||||
for(int32_t i = 0; i < size; ++i) {
|
|
||||||
SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i);
|
|
||||||
tfree(pTableReq->name);
|
|
||||||
|
|
||||||
if (pTableReq->type == TSDB_NORMAL_TABLE) {
|
|
||||||
tfree(pTableReq->ntbCfg.pSchema);
|
|
||||||
} else if (pTableReq->type == TSDB_CHILD_TABLE) {
|
|
||||||
tfree(pTableReq->ctbCfg.pTag);
|
|
||||||
} else {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayDestroy(pTbBatch->req.pArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t doCheckAndBuildCreateCTableReq(SCreateTableSql* pCreateTable, SParseContext* pCtx, SMsgBuf* pMsgBuf, SArray** pBufArray) {
|
|
||||||
const char* msg1 = "invalid table name";
|
|
||||||
const char* msg2 = "tags number not matched";
|
|
||||||
const char* msg3 = "tag value too long";
|
|
||||||
const char* msg4 = "illegal value or data overflow";
|
|
||||||
|
|
||||||
int32_t code = 0;
|
|
||||||
STableMeta* pSuperTableMeta = NULL;
|
|
||||||
|
|
||||||
SHashObj* pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
|
|
||||||
|
|
||||||
// super table name, create table by using dst
|
|
||||||
size_t numOfTables = taosArrayGetSize(pCreateTable->childTableInfo);
|
|
||||||
for (int32_t j = 0; j < numOfTables; ++j) {
|
|
||||||
SCreatedTableInfo* pCreateTableInfo = taosArrayGet(pCreateTable->childTableInfo, j);
|
|
||||||
|
|
||||||
SToken* pSTableNameToken = &pCreateTableInfo->stbName;
|
|
||||||
code = parserValidateNameToken(pSTableNameToken);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SName name = {0};
|
|
||||||
code = createSName(&name, pSTableNameToken, pCtx, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SKVRowBuilder kvRowBuilder = {0};
|
|
||||||
if (tdInitKVRowBuilder(&kvRowBuilder) < 0) {
|
|
||||||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SArray* pValList = pCreateTableInfo->pTagVals;
|
|
||||||
size_t numOfInputTag = taosArrayGetSize(pValList);
|
|
||||||
|
|
||||||
code = catalogGetTableMeta(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &name, &pSuperTableMeta);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(pSuperTableMeta != NULL);
|
|
||||||
|
|
||||||
// too long tag values will return invalid sql, not be truncated automatically
|
|
||||||
SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta);
|
|
||||||
STableComInfo tinfo = getTableInfo(pSuperTableMeta);
|
|
||||||
|
|
||||||
SArray* pNameList = NULL;
|
|
||||||
size_t numOfBoundTags = 0;
|
|
||||||
int32_t schemaSize = getNumOfTags(pSuperTableMeta);
|
|
||||||
|
|
||||||
if (pCreateTableInfo->pTagNames) {
|
|
||||||
pNameList = pCreateTableInfo->pTagNames;
|
|
||||||
numOfBoundTags = taosArrayGetSize(pNameList);
|
|
||||||
|
|
||||||
if (numOfInputTag != numOfBoundTags || schemaSize < numOfInputTag) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool findColumnIndex = false;
|
|
||||||
for (int32_t i = 0; i < numOfBoundTags; ++i) {
|
|
||||||
SToken* sToken = taosArrayGet(pNameList, i);
|
|
||||||
|
|
||||||
char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW] = {0}; // create tmp buf to avoid alter orginal sqlstr
|
|
||||||
strncpy(tmpTokenBuf, sToken->z, sToken->n);
|
|
||||||
sToken->z = tmpTokenBuf;
|
|
||||||
|
|
||||||
// if (TK_STRING == sToken->type) {
|
|
||||||
// tscDequoteAndTrimToken(sToken);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (TK_ID == sToken->type) {
|
|
||||||
// tscRmEscapeAndTrimToken(sToken);
|
|
||||||
// }
|
|
||||||
|
|
||||||
SListItem* pItem = taosArrayGet(pValList, i);
|
|
||||||
|
|
||||||
findColumnIndex = false;
|
|
||||||
|
|
||||||
// todo speedup by using hash list
|
|
||||||
for (int32_t t = 0; t < schemaSize; ++t) {
|
|
||||||
if (strncmp(sToken->z, pTagSchema[t].name, sToken->n) == 0 && strlen(pTagSchema[t].name) == sToken->n) {
|
|
||||||
SSchema* pSchema = &pTagSchema[t];
|
|
||||||
|
|
||||||
char tagVal[TSDB_MAX_TAGS_LEN] = {0};
|
|
||||||
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
|
|
||||||
if (pItem->pVar.nLen > pSchema->bytes) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
} else if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) {
|
|
||||||
if (pItem->pVar.nType == TSDB_DATA_TYPE_BINARY) {
|
|
||||||
// code = convertTimestampStrToInt64(&(pItem->pVar), tinfo.precision);
|
|
||||||
// if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
// return buildInvalidOperationMsg(pMsgBuf, msg4);
|
|
||||||
// }
|
|
||||||
} else if (pItem->pVar.nType == TSDB_DATA_TYPE_TIMESTAMP) {
|
|
||||||
pItem->pVar.i = convertTimePrecision(pItem->pVar.i, TSDB_TIME_PRECISION_NANO, tinfo.precision);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code = taosVariantDump(&(pItem->pVar), tagVal, pSchema->type, true);
|
|
||||||
|
|
||||||
// check again after the convert since it may be converted from binary to nchar.
|
|
||||||
if (IS_VAR_DATA_TYPE(pSchema->type)) {
|
|
||||||
int16_t len = varDataTLen(tagVal);
|
|
||||||
if (len > pSchema->bytes) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg4);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal);
|
|
||||||
|
|
||||||
findColumnIndex = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!findColumnIndex) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
// return buildInvalidOperationMsg(pMsgBuf, "invalid tag name", sToken->z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (schemaSize != numOfInputTag) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = doParseSerializeTagValue(pTagSchema, numOfInputTag, &kvRowBuilder, pValList, tinfo.precision, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SKVRow row = tdGetKVRowFromBuilder(&kvRowBuilder);
|
|
||||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
|
||||||
if (row == NULL) {
|
|
||||||
code = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
tdSortKVRowByColIdx(row);
|
|
||||||
|
|
||||||
SName tableName = {0};
|
|
||||||
code = createSName(&tableName, &pCreateTableInfo->name, pCtx, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a appropriate vgroup to accommodate this table , according to the table name
|
|
||||||
SVgroupInfo info = {0};
|
|
||||||
code = catalogGetTableHashVgroup(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &tableName, &info);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
addCreateTbReqIntoVgroup(pVgroupHashmap, &tableName, row, pSuperTableMeta->uid, &info);
|
|
||||||
tfree(pSuperTableMeta);
|
|
||||||
}
|
|
||||||
|
|
||||||
*pBufArray = doSerializeVgroupCreateTableInfo(pVgroupHashmap);
|
|
||||||
if (*pBufArray == NULL) {
|
|
||||||
code = terrno;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
taosHashCleanup(pVgroupHashmap);
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
|
|
||||||
_error:
|
|
||||||
taosHashCleanup(pVgroupHashmap);
|
|
||||||
tfree(pSuperTableMeta);
|
|
||||||
terrno = code;
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t serializeVgroupTablesBatchImpl(SVgroupTablesBatch* pTbBatch, SArray* pBufArray) {
|
|
||||||
int tlen = sizeof(SMsgHead) + tSerializeSVCreateTbBatchReq(NULL, &(pTbBatch->req));
|
|
||||||
void* buf = malloc(tlen);
|
|
||||||
if (buf == NULL) {
|
|
||||||
// TODO: handle error
|
|
||||||
}
|
|
||||||
|
|
||||||
((SMsgHead*)buf)->vgId = htonl(pTbBatch->info.vgId);
|
|
||||||
((SMsgHead*)buf)->contLen = htonl(tlen);
|
|
||||||
|
|
||||||
void* pBuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
|
|
||||||
tSerializeSVCreateTbBatchReq(&pBuf, &(pTbBatch->req));
|
|
||||||
|
|
||||||
SVgDataBlocks* pVgData = calloc(1, sizeof(SVgDataBlocks));
|
|
||||||
pVgData->vg = pTbBatch->info;
|
|
||||||
pVgData->pData = buf;
|
|
||||||
pVgData->size = tlen;
|
|
||||||
pVgData->numOfTables = (int32_t) taosArrayGetSize(pTbBatch->req.pArray);
|
|
||||||
|
|
||||||
taosArrayPush(pBufArray, &pVgData);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t doBuildSingleTableBatchReq(SName* pTableName, SArray* pColumns, SVgroupInfo* pVgroupInfo, SVgroupTablesBatch* pBatch) {
|
|
||||||
struct SVCreateTbReq req = {0};
|
|
||||||
req.type = TD_NORMAL_TABLE;
|
|
||||||
req.name = strdup(tNameGetTableName(pTableName));
|
|
||||||
|
|
||||||
req.ntbCfg.nCols = taosArrayGetSize(pColumns);
|
|
||||||
int32_t num = req.ntbCfg.nCols;
|
|
||||||
|
|
||||||
req.ntbCfg.pSchema = calloc(num, sizeof(SSchema));
|
|
||||||
for(int32_t i = 0; i < num; ++i) {
|
|
||||||
SSchema* pSchema = taosArrayGet(pColumns, i);
|
|
||||||
memcpy(&req.ntbCfg.pSchema[i], pSchema, sizeof(SSchema));
|
|
||||||
}
|
|
||||||
|
|
||||||
pBatch->info = *pVgroupInfo;
|
|
||||||
pBatch->req.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq));
|
|
||||||
if (pBatch->req.pArray == NULL) {
|
|
||||||
return TSDB_CODE_QRY_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayPush(pBatch->req.pArray, &req);
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t doCheckAndBuildCreateTableReq(SCreateTableSql* pCreateTable, SParseContext* pCtx, SMsgBuf* pMsgBuf, char** pOutput, int32_t* len) {
|
|
||||||
SArray* pBufArray = NULL;
|
|
||||||
int32_t code = 0;
|
|
||||||
|
|
||||||
// it is a sql statement to create a normal table
|
|
||||||
if (pCreateTable->childTableInfo == NULL) {
|
|
||||||
assert(taosArrayGetSize(pCreateTable->colInfo.pColumns) > 0 && pCreateTable->colInfo.pTagColumns == NULL);
|
|
||||||
code = doCheckForCreateTable(pCreateTable, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
SName tableName = {0};
|
|
||||||
code = createSName(&tableName, &pCreateTable->name, pCtx, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
SVgroupInfo info = {0};
|
|
||||||
catalogGetTableHashVgroup(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &tableName, &info);
|
|
||||||
|
|
||||||
SVgroupTablesBatch tbatch = {0};
|
|
||||||
code = doBuildSingleTableBatchReq(&tableName, pCreateTable->colInfo.pColumns, &info, &tbatch);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBufArray = taosArrayInit(1, POINTER_BYTES);
|
|
||||||
if (pBufArray == NULL) {
|
|
||||||
return TSDB_CODE_QRY_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
serializeVgroupTablesBatchImpl(&tbatch, pBufArray);
|
|
||||||
destroyCreateTbReqBatch(&tbatch);
|
|
||||||
} else { // it is a child table, created according to a super table
|
|
||||||
code = doCheckAndBuildCreateCTableReq(pCreateTable, pCtx, pMsgBuf, &pBufArray);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SVnodeModifOpStmtInfo* pStmtInfo = calloc(1, sizeof(SVnodeModifOpStmtInfo));
|
|
||||||
pStmtInfo->nodeType = TSDB_SQL_CREATE_TABLE;
|
|
||||||
pStmtInfo->pDataBlocks = pBufArray;
|
|
||||||
|
|
||||||
*pOutput = (char*) pStmtInfo;
|
|
||||||
*len = sizeof(SVnodeModifOpStmtInfo);
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
SArray* doSerializeVgroupCreateTableInfo(SHashObj* pVgroupHashmap) {
|
|
||||||
SArray* pBufArray = taosArrayInit(taosHashGetSize(pVgroupHashmap), sizeof(void*));
|
|
||||||
|
|
||||||
SVgroupTablesBatch* pTbBatch = NULL;
|
|
||||||
do {
|
|
||||||
pTbBatch = taosHashIterate(pVgroupHashmap, pTbBatch);
|
|
||||||
if (pTbBatch == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*int32_t code = */serializeVgroupTablesBatchImpl(pTbBatch, pBufArray);
|
|
||||||
destroyCreateTbReqBatch(pTbBatch);
|
|
||||||
} while (true);
|
|
||||||
|
|
||||||
return pBufArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen) {
|
|
||||||
int32_t code = 0;
|
|
||||||
|
|
||||||
SDclStmtInfo* pDcl = calloc(1, sizeof(SDclStmtInfo));
|
|
||||||
|
|
||||||
SMsgBuf m = {.buf = msgBuf, .len = msgBufLen};
|
|
||||||
SMsgBuf* pMsgBuf = &m;
|
|
||||||
|
|
||||||
pDcl->epSet = pCtx->mgmtEpSet;
|
|
||||||
|
|
||||||
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) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parserValidateIdToken(pName) != TSDB_CODE_SUCCESS) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pInfo->type == TSDB_SQL_CREATE_USER) {
|
|
||||||
if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
code = TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (pUser->type == TSDB_ALTER_USER_PASSWD) {
|
|
||||||
if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
code = TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
} 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 {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg4);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->pMsg = (char*)buildUserManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen);
|
|
||||||
pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_USER) ? TDMT_MND_CREATE_USER : TDMT_MND_ALTER_USER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_CREATE_ACCT:
|
|
||||||
case TSDB_SQL_ALTER_ACCT: {
|
|
||||||
const char* msg1 = "invalid state option, available options[no, r, w, all]";
|
|
||||||
const char* msg2 = "invalid user/account name";
|
|
||||||
const char* msg3 = "name too long";
|
|
||||||
|
|
||||||
SToken* pName = &pInfo->pMiscInfo->user.user;
|
|
||||||
SToken* pPwd = &pInfo->pMiscInfo->user.passwd;
|
|
||||||
|
|
||||||
if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
|
||||||
code = TSDB_CODE_TSC_INVALID_OPERATION;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pName->n >= TSDB_USER_LEN) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg3);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parserValidateNameToken(pName) != TSDB_CODE_SUCCESS) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SCreateAcctInfo* pAcctOpt = &pInfo->pMiscInfo->acctOpt;
|
|
||||||
if (pAcctOpt->stat.n > 0) {
|
|
||||||
if (pAcctOpt->stat.z[0] == 'r' && pAcctOpt->stat.n == 1) {
|
|
||||||
} else if (pAcctOpt->stat.z[0] == 'w' && pAcctOpt->stat.n == 1) {
|
|
||||||
} 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 {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->pMsg = (char*)buildAcctManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen);
|
|
||||||
pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_ACCT) ? TDMT_MND_CREATE_ACCT : TDMT_MND_ALTER_ACCT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_DROP_ACCT:
|
|
||||||
case TSDB_SQL_DROP_USER: {
|
|
||||||
pDcl->pMsg = (char*)buildDropUserMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen);
|
|
||||||
pDcl->msgType = (pInfo->type == TSDB_SQL_DROP_ACCT) ? TDMT_MND_DROP_ACCT : TDMT_MND_DROP_USER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_SHOW: {
|
|
||||||
SShowInfo* pShowInfo = &pInfo->pMiscInfo->showOpt;
|
|
||||||
code = setShowInfo(pShowInfo, pCtx, (void**)&pDcl->pMsg, &pDcl->msgLen, &pDcl->epSet, &pDcl->pExtension, pMsgBuf);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->msgType = (pShowInfo->showType == TSDB_MGMT_TABLE_TABLE) ? TDMT_VND_SHOW_TABLES : TDMT_MND_SHOW;
|
|
||||||
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) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SName n = {0};
|
|
||||||
int32_t ret = tNameSetDbName(&n, pCtx->acctId, pToken->z, pToken->n);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SUseDbReq usedbReq = {0};
|
|
||||||
tNameExtractFullName(&n, usedbReq.db);
|
|
||||||
|
|
||||||
int32_t bufLen = tSerializeSUseDbReq(NULL, 0, &usedbReq);
|
|
||||||
void* pBuf = malloc(bufLen);
|
|
||||||
tSerializeSUseDbReq(pBuf, bufLen, &usedbReq);
|
|
||||||
|
|
||||||
pDcl->pMsg = pBuf;
|
|
||||||
pDcl->msgLen = bufLen;
|
|
||||||
pDcl->msgType = TDMT_MND_USE_DB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_ALTER_DB:
|
|
||||||
case TSDB_SQL_CREATE_DB: {
|
|
||||||
const char* msg1 = "invalid db name";
|
|
||||||
const char* msg2 = "name too long";
|
|
||||||
|
|
||||||
SCreateDbInfo* pCreateDB = &(pInfo->pMiscInfo->dbOpt);
|
|
||||||
if (pCreateDB->dbname.n >= TSDB_DB_NAME_LEN) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg2);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[TSDB_DB_NAME_LEN] = {0};
|
|
||||||
SToken token = taosTokenDup(&pCreateDB->dbname, buf, tListLen(buf));
|
|
||||||
|
|
||||||
if (parserValidateNameToken(&token) != TSDB_CODE_SUCCESS) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t bufLen = 0;
|
|
||||||
char* pBuf = buildCreateDbMsg(pCreateDB, &bufLen, pCtx, pMsgBuf);
|
|
||||||
|
|
||||||
pDcl->pMsg = pBuf;
|
|
||||||
pDcl->msgLen = bufLen;
|
|
||||||
pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_DB) ? TDMT_MND_CREATE_DB : TDMT_MND_ALTER_DB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_DROP_DB: {
|
|
||||||
const char* msg1 = "invalid database name";
|
|
||||||
|
|
||||||
assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1);
|
|
||||||
SToken* dbName = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
|
||||||
|
|
||||||
SName name = {0};
|
|
||||||
code = tNameSetDbName(&name, pCtx->acctId, dbName->z, dbName->n);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDropDbReq dropdbReq = {0};
|
|
||||||
code = tNameExtractFullName(&name, dropdbReq.db);
|
|
||||||
dropdbReq.ignoreNotExists = pInfo->pMiscInfo->existsCheck ? 1 : 0;
|
|
||||||
assert(code == TSDB_CODE_SUCCESS && name.type == TSDB_DB_NAME_T);
|
|
||||||
|
|
||||||
int32_t bufLen = tSerializeSDropDbReq(NULL, 0, &dropdbReq);
|
|
||||||
void* pBuf = malloc(bufLen);
|
|
||||||
tSerializeSDropDbReq(pBuf, bufLen, &dropdbReq);
|
|
||||||
|
|
||||||
pDcl->msgType = TDMT_MND_DROP_DB;
|
|
||||||
pDcl->msgLen = bufLen;
|
|
||||||
pDcl->pMsg = pBuf;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_CREATE_STABLE: {
|
|
||||||
SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
|
|
||||||
if ((code = doCheckForCreateTable(pCreateTable, pMsgBuf)) != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = code;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->pMsg = buildCreateStbReq(pCreateTable, &pDcl->msgLen, pCtx, pMsgBuf);
|
|
||||||
pDcl->msgType = TDMT_MND_CREATE_STB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_DROP_TABLE: {
|
|
||||||
pDcl->pMsg = buildDropStableReq(pInfo, &pDcl->msgLen, pCtx, pMsgBuf);
|
|
||||||
if (pDcl->pMsg == NULL) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->msgType = TDMT_MND_DROP_STB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_CREATE_DNODE: {
|
|
||||||
pDcl->pMsg = (char*)buildCreateDnodeMsg(pInfo, &pDcl->msgLen, pMsgBuf);
|
|
||||||
if (pDcl->pMsg == NULL) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->msgType = TDMT_MND_CREATE_DNODE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_SQL_DROP_DNODE: {
|
|
||||||
pDcl->pMsg = (char*)buildDropDnodeMsg(pInfo, &pDcl->msgLen, pMsgBuf);
|
|
||||||
if (pDcl->pMsg == NULL) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDcl->msgType = TDMT_MND_DROP_DNODE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pDcl;
|
|
||||||
|
|
||||||
_error:
|
|
||||||
terrno = code;
|
|
||||||
tfree(pDcl);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SVnodeModifOpStmtInfo* qParserValidateCreateTbSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen) {
|
|
||||||
SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
|
|
||||||
assert(pCreateTable->type == TSDB_SQL_CREATE_TABLE);
|
|
||||||
|
|
||||||
SMsgBuf m = {.buf = msgBuf, .len = msgBufLen};
|
|
||||||
SMsgBuf* pMsgBuf = &m;
|
|
||||||
|
|
||||||
SVnodeModifOpStmtInfo* pModifSqlStmt = NULL;
|
|
||||||
|
|
||||||
int32_t msgLen = 0;
|
|
||||||
int32_t code = doCheckAndBuildCreateTableReq(pCreateTable, pCtx, pMsgBuf, (char**) &pModifSqlStmt, &msgLen);
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
terrno = code;
|
|
||||||
tfree(pModifSqlStmt);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pModifSqlStmt;
|
|
||||||
}
|
|
|
@ -17,8 +17,7 @@
|
||||||
|
|
||||||
#include "catalog.h"
|
#include "catalog.h"
|
||||||
#include "parserUtil.h"
|
#include "parserUtil.h"
|
||||||
#include "queryInfoUtil.h"
|
#include "querynodes.h"
|
||||||
#include "tmsg.h"
|
|
||||||
|
|
||||||
#define IS_RAW_PAYLOAD(t) \
|
#define IS_RAW_PAYLOAD(t) \
|
||||||
(((int)(t)) == PAYLOAD_TYPE_RAW) // 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert
|
(((int)(t)) == PAYLOAD_TYPE_RAW) // 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert
|
||||||
|
|
|
@ -16,9 +16,7 @@
|
||||||
#include "insertParser.h"
|
#include "insertParser.h"
|
||||||
|
|
||||||
#include "dataBlockMgt.h"
|
#include "dataBlockMgt.h"
|
||||||
#include "parserInt.h"
|
|
||||||
#include "parserUtil.h"
|
#include "parserUtil.h"
|
||||||
#include "queryInfoUtil.h"
|
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "ttime.h"
|
#include "ttime.h"
|
||||||
#include "ttoken.h"
|
#include "ttoken.h"
|
||||||
|
@ -61,9 +59,14 @@ typedef struct SInsertParseContext {
|
||||||
SArray* pTableDataBlocks; // global
|
SArray* pTableDataBlocks; // global
|
||||||
SArray* pVgDataBlocks; // global
|
SArray* pVgDataBlocks; // global
|
||||||
int32_t totalNum;
|
int32_t totalNum;
|
||||||
SVnodeModifOpStmtInfo* pOutput;
|
SVnodeModifOpStmt* pOutput;
|
||||||
} SInsertParseContext;
|
} SInsertParseContext;
|
||||||
|
|
||||||
|
typedef int32_t (*_row_append_fn_t)(const void *value, int32_t len, void *param);
|
||||||
|
|
||||||
|
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
|
||||||
|
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
|
||||||
|
|
||||||
static int32_t skipInsertInto(SInsertParseContext* pCxt) {
|
static int32_t skipInsertInto(SInsertParseContext* pCxt) {
|
||||||
SToken sToken;
|
SToken sToken;
|
||||||
NEXT_TOKEN(pCxt->pSql, sToken);
|
NEXT_TOKEN(pCxt->pSql, sToken);
|
||||||
|
@ -95,6 +98,66 @@ static int32_t buildName(SInsertParseContext* pCxt, SToken* pStname, char* fullD
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) {
|
||||||
|
const char* msg1 = "name too long";
|
||||||
|
const char* msg2 = "invalid database name";
|
||||||
|
const char* msg3 = "db is not specified";
|
||||||
|
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
char* p = strnchr(pTableName->z, TS_PATH_DELIMITER[0], pTableName->n, true);
|
||||||
|
|
||||||
|
if (p != NULL) { // db has been specified in sql string so we ignore current db path
|
||||||
|
assert(*p == TS_PATH_DELIMITER[0]);
|
||||||
|
|
||||||
|
int32_t dbLen = p - pTableName->z;
|
||||||
|
char name[TSDB_DB_FNAME_LEN] = {0};
|
||||||
|
strncpy(name, pTableName->z, dbLen);
|
||||||
|
dbLen = strdequote(name);
|
||||||
|
|
||||||
|
code = tNameSetDbName(pName, pParseCtx->acctId, name, dbLen);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tbLen = pTableName->n - dbLen - 1;
|
||||||
|
char tbname[TSDB_TABLE_FNAME_LEN] = {0};
|
||||||
|
strncpy(tbname, p + 1, tbLen);
|
||||||
|
/*tbLen = */strdequote(tbname);
|
||||||
|
|
||||||
|
code = tNameFromString(pName, tbname, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pTableName->n < TSDB_TABLE_FNAME_LEN);
|
||||||
|
|
||||||
|
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||||
|
strncpy(name, pTableName->z, pTableName->n);
|
||||||
|
strdequote(name);
|
||||||
|
|
||||||
|
if (pParseCtx->db == NULL) {
|
||||||
|
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
code = tNameSetDbName(pName, pParseCtx->acctId, pParseCtx->db, strlen(pParseCtx->db));
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
code = buildInvalidOperationMsg(pMsgBuf, msg2);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = tNameFromString(pName, name, T_NAME_TABLE);
|
||||||
|
if (code != 0) {
|
||||||
|
code = buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t getTableMeta(SInsertParseContext* pCxt, SToken* pTname) {
|
static int32_t getTableMeta(SInsertParseContext* pCxt, SToken* pTname) {
|
||||||
SName name = {0};
|
SName name = {0};
|
||||||
createSName(&name, pTname, pCxt->pComCxt, &pCxt->msg);
|
createSName(&name, pTname, pCxt->pComCxt, &pCxt->msg);
|
||||||
|
@ -258,6 +321,231 @@ static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, uint32_t type, char* tmpTokenBuf, SMsgBuf* pMsgBuf) {
|
||||||
|
if ((pToken->type != TK_NOW && pToken->type != TK_INTEGER && pToken->type != TK_STRING && pToken->type != TK_FLOAT && pToken->type != TK_BOOL &&
|
||||||
|
pToken->type != TK_NULL && pToken->type != TK_HEX && pToken->type != TK_OCT && pToken->type != TK_BIN) ||
|
||||||
|
(pToken->n == 0) || (pToken->type == TK_RP)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_NUMERIC_TYPE(type) && pToken->n == 0) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid numeric data", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove quotation marks
|
||||||
|
if (TSDB_DATA_TYPE_BINARY == type) {
|
||||||
|
if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete escape character: \\, \', \"
|
||||||
|
char delim = pToken->z[0];
|
||||||
|
int32_t cnt = 0;
|
||||||
|
int32_t j = 0;
|
||||||
|
for (uint32_t k = 1; k < pToken->n - 1; ++k) {
|
||||||
|
if (pToken->z[k] == '\\' || (pToken->z[k] == delim && pToken->z[k + 1] == delim)) {
|
||||||
|
tmpTokenBuf[j] = pToken->z[k + 1];
|
||||||
|
cnt++;
|
||||||
|
j++;
|
||||||
|
k++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmpTokenBuf[j] = pToken->z[k];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpTokenBuf[j] = 0;
|
||||||
|
pToken->z = tmpTokenBuf;
|
||||||
|
pToken->n -= 2 + cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isNullStr(SToken *pToken) {
|
||||||
|
return (pToken->type == TK_NULL) || ((pToken->type == TK_STRING) && (pToken->n != 0) &&
|
||||||
|
(strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE int32_t toDouble(SToken *pToken, double *value, char **endPtr) {
|
||||||
|
errno = 0;
|
||||||
|
*value = strtold(pToken->z, endPtr);
|
||||||
|
|
||||||
|
// not a valid integer number, return error
|
||||||
|
if ((*endPtr - pToken->z) != pToken->n) {
|
||||||
|
return TK_ILLEGAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pToken->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf) {
|
||||||
|
int64_t iv;
|
||||||
|
char *endptr = NULL;
|
||||||
|
bool isSigned = false;
|
||||||
|
|
||||||
|
int32_t code = checkAndTrimValue(pToken, pSchema->type, tmpTokenBuf, pMsgBuf);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
|
||||||
|
int64_t tmpVal = 0;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(getNullValue(pSchema->type), 0, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pSchema->type) {
|
||||||
|
case TSDB_DATA_TYPE_BOOL: {
|
||||||
|
if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) {
|
||||||
|
if (strncmp(pToken->z, "true", pToken->n) == 0) {
|
||||||
|
return func(&TRUE_VALUE, pSchema->bytes, param);
|
||||||
|
} else if (strncmp(pToken->z, "false", pToken->n) == 0) {
|
||||||
|
return func(&FALSE_VALUE, pSchema->bytes, param);
|
||||||
|
} else {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
|
||||||
|
}
|
||||||
|
} else if (pToken->type == TK_INTEGER) {
|
||||||
|
return func(((strtoll(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param);
|
||||||
|
} else if (pToken->type == TK_FLOAT) {
|
||||||
|
return func(((strtod(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param);
|
||||||
|
} else {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_TINYINT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_TINYINT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tmpVal = (uint8_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_UTINYINT:{
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_UTINYINT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
uint8_t tmpVal = (uint8_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_SMALLINT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_SMALLINT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
int16_t tmpVal = (int16_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_USMALLINT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_USMALLINT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
uint16_t tmpVal = (uint16_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_INT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
|
||||||
|
} else if (!IS_VALID_INT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
int32_t tmpVal = (int32_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_UINT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
|
||||||
|
} else if (!IS_VALID_UINT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
uint32_t tmpVal = (uint32_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_BIGINT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_BIGINT(iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "bigint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
return func(&iv, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_UBIGINT: {
|
||||||
|
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_UBIGINT((uint64_t)iv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "unsigned bigint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
uint64_t tmpVal = (uint64_t)iv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_FLOAT: {
|
||||||
|
double dv;
|
||||||
|
if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
|
||||||
|
}
|
||||||
|
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
|
||||||
|
}
|
||||||
|
float tmpVal = (float)dv;
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE: {
|
||||||
|
double dv;
|
||||||
|
if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
|
||||||
|
}
|
||||||
|
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
|
||||||
|
}
|
||||||
|
return func(&dv, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_BINARY: {
|
||||||
|
// Too long values will raise the invalid sql error message
|
||||||
|
if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "string data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(pToken->z, pToken->n, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_NCHAR: {
|
||||||
|
return func(pToken->z, pToken->n, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||||
|
int64_t tmpVal;
|
||||||
|
if (parseTime(end, pToken, timePrec, &tmpVal, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||||
|
return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(&tmpVal, pSchema->bytes, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct SMemParam {
|
typedef struct SMemParam {
|
||||||
SRowBuilder* rb;
|
SRowBuilder* rb;
|
||||||
SSchema* schema;
|
SSchema* schema;
|
||||||
|
@ -634,7 +922,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
|
||||||
// [(field1_name, ...)]
|
// [(field1_name, ...)]
|
||||||
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
|
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
|
||||||
// [...];
|
// [...];
|
||||||
int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo) {
|
int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery) {
|
||||||
SInsertParseContext context = {
|
SInsertParseContext context = {
|
||||||
.pComCxt = pContext,
|
.pComCxt = pContext,
|
||||||
.pSql = (char*) pContext->pSql,
|
.pSql = (char*) pContext->pSql,
|
||||||
|
@ -643,7 +931,7 @@ int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo) {
|
||||||
.pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false),
|
.pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false),
|
||||||
.pTableBlockHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false),
|
.pTableBlockHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false),
|
||||||
.totalNum = 0,
|
.totalNum = 0,
|
||||||
.pOutput = calloc(1, sizeof(SVnodeModifOpStmtInfo))
|
.pOutput = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (NULL == context.pVgroupsHashObj || NULL == context.pTableBlockHashObj || NULL == context.pOutput) {
|
if (NULL == context.pVgroupsHashObj || NULL == context.pTableBlockHashObj || NULL == context.pOutput) {
|
||||||
|
@ -651,8 +939,7 @@ int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo) {
|
||||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pInfo = context.pOutput;
|
(*pQuery)->pRoot = (SNode*)context.pOutput;
|
||||||
context.pOutput->nodeType = TSDB_SQL_INSERT;
|
|
||||||
context.pOutput->payloadType = PAYLOAD_TYPE_KV;
|
context.pOutput->payloadType = PAYLOAD_TYPE_KV;
|
||||||
|
|
||||||
int32_t code = skipInsertInto(&context);
|
int32_t code = skipInsertInto(&context);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
#include "astGenerator.h"
|
#include "astGenerator.h"
|
||||||
#include "parserInt.h"
|
#include "parserInt.h"
|
||||||
#include "parserUtil.h"
|
#include "parserUtil.h"
|
||||||
|
@ -260,3 +261,36 @@ void qDestroyQuery(SQueryNode* pQueryNode) {
|
||||||
destroyQueryInfo(pQueryStmtInfo);
|
destroyQueryInfo(pQueryStmtInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
#include "insertParser.h"
|
||||||
|
#include "parserImpl.h"
|
||||||
|
#include "ttoken.h"
|
||||||
|
|
||||||
|
static bool isInsertSql(const char* pStr, size_t length) {
|
||||||
|
int32_t index = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
SToken t0 = tStrGetToken((char*) pStr, &index, false);
|
||||||
|
if (t0.type != TK_LP) {
|
||||||
|
return t0.type == TK_INSERT || t0.type == TK_IMPORT;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery) {
|
||||||
|
if (isInsertSql(pCxt->pSql, pCxt->sqlLen)) {
|
||||||
|
return parseInsertSql(pCxt, pQuery);
|
||||||
|
} else {
|
||||||
|
return parseQuerySql(pCxt, pQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qDestroyQuery(SQuery* pQueryNode) {
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
#include "parserImpl.h"
|
#include "parserImpl.h"
|
||||||
|
|
||||||
#include "astCreateContext.h"
|
#include "astCreateContext.h"
|
||||||
|
#include "catalog.h"
|
||||||
#include "functionMgt.h"
|
#include "functionMgt.h"
|
||||||
#include "parserInt.h"
|
#include "parserUtil.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
|
#include "tname.h"
|
||||||
#include "ttime.h"
|
#include "ttime.h"
|
||||||
#include "ttoken.h"
|
#include "ttoken.h"
|
||||||
|
|
||||||
|
@ -174,20 +176,20 @@ static uint32_t getToken(const char* z, uint32_t* tokenId) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EStmtType getStmtType(const SNode* pRootNode) {
|
static bool isCmd(const SNode* pRootNode) {
|
||||||
if (NULL == pRootNode) {
|
if (NULL == pRootNode) {
|
||||||
return STMT_TYPE_CMD;
|
return true;
|
||||||
}
|
}
|
||||||
switch (nodeType(pRootNode)) {
|
switch (nodeType(pRootNode)) {
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
return STMT_TYPE_QUERY;
|
return false;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return STMT_TYPE_CMD;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
int32_t doParse(SParseContext* pParseCxt, SQuery** pQuery) {
|
||||||
SAstCreateContext cxt;
|
SAstCreateContext cxt;
|
||||||
createAstCreateContext(pParseCxt, &cxt);
|
createAstCreateContext(pParseCxt, &cxt);
|
||||||
void *pParser = NewParseAlloc(malloc);
|
void *pParser = NewParseAlloc(malloc);
|
||||||
|
@ -236,8 +238,11 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
abort_parse:
|
abort_parse:
|
||||||
NewParseFree(pParser, free);
|
NewParseFree(pParser, free);
|
||||||
destroyAstCreateContext(&cxt);
|
destroyAstCreateContext(&cxt);
|
||||||
pQuery->stmtType = getStmtType(cxt.pRootNode);
|
if (cxt.valid) {
|
||||||
pQuery->pRoot = cxt.pRootNode;
|
*pQuery = calloc(1, sizeof(SQuery));
|
||||||
|
(*pQuery)->isCmd = isCmd(cxt.pRootNode);
|
||||||
|
(*pQuery)->pRoot = cxt.pRootNode;
|
||||||
|
}
|
||||||
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
|
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,16 +1059,16 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = translateQuery(&cxt, pQuery->pRoot);
|
code = translateQuery(&cxt, pQuery->pRoot);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code && STMT_TYPE_QUERY == pQuery->stmtType) {
|
if (TSDB_CODE_SUCCESS == code && !pQuery->isCmd) {
|
||||||
code = setReslutSchema(&cxt, pQuery);
|
code = setReslutSchema(&cxt, pQuery);
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t parser(SParseContext* pParseCxt, SQuery* pQuery) {
|
int32_t parseQuerySql(SParseContext* pCxt, SQuery** pQuery) {
|
||||||
int32_t code = doParse(pParseCxt, pQuery);
|
int32_t code = doParse(pCxt, pQuery);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = doTranslate(pParseCxt, pQuery);
|
code = doTranslate(pCxt, *pQuery);
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,377 +0,0 @@
|
||||||
#include "os.h"
|
|
||||||
#include "queryInfoUtil.h"
|
|
||||||
#include "function.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "parserUtil.h"
|
|
||||||
|
|
||||||
static struct SSchema _s = {
|
|
||||||
.colId = TSDB_TBNAME_COLUMN_INDEX,
|
|
||||||
.type = TSDB_DATA_TYPE_BINARY,
|
|
||||||
.bytes = TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE,
|
|
||||||
.name = "tbname",
|
|
||||||
};
|
|
||||||
|
|
||||||
SSchema* getTbnameColumnSchema() {
|
|
||||||
return &_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
SArray* getCurrentExprList(SQueryStmtInfo* pQueryInfo) {
|
|
||||||
assert(pQueryInfo != NULL && pQueryInfo->exprListLevelIndex >= 0 && pQueryInfo->exprListLevelIndex < 10);
|
|
||||||
return pQueryInfo->exprList[pQueryInfo->exprListLevelIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo) {
|
|
||||||
SArray* pExprList = getCurrentExprList(pQueryInfo);
|
|
||||||
return taosArrayGetSize(pExprList);
|
|
||||||
}
|
|
||||||
|
|
||||||
SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
|
|
||||||
assert(pTableMeta != NULL && pTableMeta->schema != NULL && colIndex >= 0 && colIndex < (getNumOfColumns(pTableMeta) + getNumOfTags(pTableMeta)));
|
|
||||||
|
|
||||||
SSchema* pSchema = (SSchema*) pTableMeta->schema;
|
|
||||||
return &pSchema[colIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
STableComInfo getTableInfo(const STableMeta* pTableMeta) {
|
|
||||||
assert(pTableMeta != NULL);
|
|
||||||
return pTableMeta->tableInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t getNumOfColumns(const STableMeta* pTableMeta) {
|
|
||||||
assert(pTableMeta != NULL);
|
|
||||||
// table created according to super table, use data from super table
|
|
||||||
return getTableInfo(pTableMeta).numOfColumns;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t getNumOfTags(const STableMeta* pTableMeta) {
|
|
||||||
assert(pTableMeta != NULL);
|
|
||||||
return getTableInfo(pTableMeta).numOfTags;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSchema *getTableColumnSchema(const STableMeta *pTableMeta) {
|
|
||||||
assert(pTableMeta != NULL);
|
|
||||||
return (SSchema*) pTableMeta->schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
|
|
||||||
assert(pTableMeta != NULL && (pTableMeta->tableType == TSDB_SUPER_TABLE || pTableMeta->tableType == TSDB_CHILD_TABLE));
|
|
||||||
return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns);
|
|
||||||
}
|
|
||||||
|
|
||||||
static tExprNode* createFunctionExprNode(const char* funcName, struct SSourceParam *pParam) {
|
|
||||||
tExprNode** p = malloc(pParam->num * POINTER_BYTES);
|
|
||||||
|
|
||||||
if (pParam->pColumnList != NULL) {
|
|
||||||
for(int32_t i = 0; i < pParam->num; ++i) {
|
|
||||||
p[i] = calloc(1, sizeof(tExprNode));
|
|
||||||
p[i]->nodeType = TEXPR_COL_NODE;
|
|
||||||
|
|
||||||
SColumn* pSrc = taosArrayGetP(pParam->pColumnList, i);
|
|
||||||
SSchema* pSchema = calloc(1, sizeof(SSchema));
|
|
||||||
|
|
||||||
tstrncpy(pSchema->name, pSrc->name, tListLen(pSchema->name));
|
|
||||||
pSchema->type = pSrc->info.type;
|
|
||||||
pSchema->bytes = pSrc->info.bytes;
|
|
||||||
pSchema->colId = pSrc->info.colId;
|
|
||||||
p[i]->pSchema = pSchema;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(pParam->pColumnList == NULL);
|
|
||||||
for(int32_t i = 0; i < pParam->num; ++i) {
|
|
||||||
p[i] = taosArrayGetP(pParam->pExprNodeList, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tExprNode* pNode = calloc(1, sizeof(tExprNode));
|
|
||||||
|
|
||||||
pNode->nodeType = TEXPR_FUNCTION_NODE;
|
|
||||||
tstrncpy(pNode->_function.functionName, funcName, tListLen(pNode->_function.functionName));
|
|
||||||
pNode->_function.pChild = p;
|
|
||||||
pNode->_function.num = pParam->num;
|
|
||||||
|
|
||||||
return pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
SExprInfo* createBinaryExprInfo(tExprNode* pNode, SSchema* pResSchema) {
|
|
||||||
assert(pNode != NULL && pResSchema != NULL);
|
|
||||||
|
|
||||||
SExprInfo* pExpr = calloc(1, sizeof(SExprInfo));
|
|
||||||
if (pExpr == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pExpr->pExpr = pNode;
|
|
||||||
memcpy(&pExpr->base.resSchema, pResSchema, sizeof(SSchema));
|
|
||||||
return pExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, const char* funcName, SSourceParam* pSourceParam, SSchema* pResSchema, int16_t interSize) {
|
|
||||||
SExprInfo* pExpr = calloc(1, sizeof(SExprInfo));
|
|
||||||
if (pExpr == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t uid = 0;
|
|
||||||
if (pTableMetaInfo->pTableMeta) {
|
|
||||||
uid = pTableMetaInfo->pTableMeta->uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSqlExpr* p = &pExpr->base;
|
|
||||||
|
|
||||||
p->pColumns = calloc(pSourceParam->num, sizeof(SColumn));
|
|
||||||
p->numOfCols = pSourceParam->num;
|
|
||||||
p->interBytes = interSize;
|
|
||||||
memcpy(&p->resSchema, pResSchema, sizeof(SSchema));
|
|
||||||
|
|
||||||
if (pSourceParam->pExprNodeList != NULL) {
|
|
||||||
pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam);
|
|
||||||
return pExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SColumn* pCol = taosArrayGetP(pSourceParam->pColumnList, 0);
|
|
||||||
if (pCol->info.colId == TSDB_TBNAME_COLUMN_INDEX) {
|
|
||||||
assert(pSourceParam->num == 1);
|
|
||||||
|
|
||||||
SSchema* s = getTbnameColumnSchema();
|
|
||||||
setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, s);
|
|
||||||
|
|
||||||
pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam);
|
|
||||||
} else if (TSDB_COL_IS_UD_COL(pCol->flag) || strcmp(funcName, "block_dist") == 0) {
|
|
||||||
setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_UDC, pResSchema);
|
|
||||||
pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam);
|
|
||||||
} else {
|
|
||||||
for(int32_t i = 0; i < pSourceParam->num; ++i) {
|
|
||||||
SColumn* c = taosArrayGetP(pSourceParam->pColumnList, i);
|
|
||||||
p->pColumns[i] = *c;
|
|
||||||
}
|
|
||||||
pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level) {
|
|
||||||
assert(pExprList != NULL );
|
|
||||||
|
|
||||||
int32_t num = (int32_t) taosArrayGetSize(pExprList);
|
|
||||||
if (index == num) {
|
|
||||||
taosArrayPush(pExprList, &pExprInfo);
|
|
||||||
} else {
|
|
||||||
taosArrayInsert(pExprList, index, &pExprInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE) {
|
|
||||||
printf("add function: %s, level:%d, total:%ld\n", pExprInfo->pExpr->_function.functionName, level, taosArrayGetSize(pExprList));
|
|
||||||
} else {
|
|
||||||
printf("add operator: %s, level:%d, total:%ld\n", pExprInfo->base.resSchema.name, level, taosArrayGetSize(pExprList));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize) {
|
|
||||||
assert(pExprInfo != NULL);
|
|
||||||
|
|
||||||
SSqlExpr* pse = &pExprInfo->base;
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
pse->resSchema.type = resType;
|
|
||||||
pse->resSchema.bytes = resSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
SExprInfo* getExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index) {
|
|
||||||
assert(pQueryInfo != NULL && pQueryInfo->exprList && index >= 0);
|
|
||||||
return taosArrayGetP(getCurrentExprList(pQueryInfo), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroyExprInfo(SExprInfo* pExprInfo) {
|
|
||||||
tExprTreeDestroy(pExprInfo->pExpr, NULL);
|
|
||||||
|
|
||||||
for(int32_t i = 0; i < pExprInfo->base.numOfParams; ++i) {
|
|
||||||
taosVariantDestroy(&pExprInfo->base.param[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
tfree(pExprInfo->base.pColumns);
|
|
||||||
tfree(pExprInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dropOneLevelExprInfo(SArray* pExprInfo) {
|
|
||||||
size_t size = taosArrayGetSize(pExprInfo);
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
|
||||||
SExprInfo* pExpr = taosArrayGetP(pExprInfo, i);
|
|
||||||
destroyExprInfo(pExpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayDestroy(pExprInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel) {
|
|
||||||
for(int32_t i = 0; i < numOfLevel; ++i) {
|
|
||||||
dropOneLevelExprInfo(pExprInfo[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes) {
|
|
||||||
assert (pExpr != NULL || argument != NULL || bytes != 0);
|
|
||||||
|
|
||||||
// set parameter value
|
|
||||||
// transfer to tVariant from byte data/no ascii data
|
|
||||||
taosVariantCreateFromBinary(&pExpr->param[pExpr->numOfParams], argument, bytes, type);
|
|
||||||
pExpr->numOfParams += 1;
|
|
||||||
|
|
||||||
assert(pExpr->numOfParams <= 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t getExprFunctionId(SExprInfo *pExprInfo) {
|
|
||||||
assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assignExprInfo(SExprInfo* dst, const SExprInfo* src) {
|
|
||||||
assert(dst != NULL && src != NULL);
|
|
||||||
|
|
||||||
*dst = *src;
|
|
||||||
#if 0
|
|
||||||
if (src->base.flist.numOfFilters > 0) {
|
|
||||||
dst->base.flist.filterInfo = calloc(src->base.flist.numOfFilters, sizeof(SColumnFilterInfo));
|
|
||||||
memcpy(dst->base.flist.filterInfo, src->base.flist.filterInfo, sizeof(SColumnFilterInfo) * src->base.flist.numOfFilters);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dst->pExpr = exprdup(src->pExpr);
|
|
||||||
dst->base.pColumns = calloc(src->base.numOfCols, sizeof(SColumn));
|
|
||||||
memcpy(dst->base.pColumns, src->base.pColumns, sizeof(SColumn) * src->base.numOfCols);
|
|
||||||
|
|
||||||
memset(dst->base.param, 0, sizeof(SVariant) * tListLen(dst->base.param));
|
|
||||||
for (int32_t j = 0; j < src->base.numOfParams; ++j) {
|
|
||||||
taosVariantAssign(&dst->base.param[j], &src->base.param[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy) {
|
|
||||||
assert(src != NULL && dst != NULL);
|
|
||||||
|
|
||||||
size_t size = taosArrayGetSize(src);
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
|
||||||
SExprInfo* pExpr = taosArrayGetP(src, i);
|
|
||||||
uint64_t exprUid = pExpr->base.pColumns->uid;
|
|
||||||
|
|
||||||
if (exprUid == uid) {
|
|
||||||
if (deepcopy) {
|
|
||||||
SExprInfo* p1 = calloc(1, sizeof(SExprInfo));
|
|
||||||
assignExprInfo(p1, pExpr);
|
|
||||||
|
|
||||||
taosArrayPush(dst, &p1);
|
|
||||||
} else {
|
|
||||||
taosArrayPush(dst, &pExpr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t copyAllExprInfo(SArray* dst, const SArray* src, bool deepcopy) {
|
|
||||||
assert(src != NULL && dst != NULL);
|
|
||||||
|
|
||||||
size_t size = taosArrayGetSize(src);
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
|
||||||
SExprInfo* pExpr = taosArrayGetP(src, i);
|
|
||||||
|
|
||||||
SExprInfo* p1 = calloc(1, sizeof(SExprInfo));
|
|
||||||
assignExprInfo(p1, pExpr);
|
|
||||||
taosArrayPush(dst, &p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//void* tSqlExprDestroy(SExprInfo* pExpr) {
|
|
||||||
// if (pExpr == NULL) {
|
|
||||||
// return NULL;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SSqlExpr* p = &pExpr->base;
|
|
||||||
// for(int32_t i = 0; i < tListLen(p->param); ++i) {
|
|
||||||
// taosVariantDestroy(&p->param[i]);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (p->flist.numOfFilters > 0) {
|
|
||||||
// tfree(p->flist.filterInfo);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (pExpr->pExpr != NULL) {
|
|
||||||
// tExprTreeDestroy(pExpr->pExpr, NULL);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// tfree(pExpr);
|
|
||||||
// return NULL;
|
|
||||||
//}
|
|
||||||
|
|
||||||
int32_t getResRowLength(SArray* pExprList) {
|
|
||||||
size_t num = taosArrayGetSize(pExprList);
|
|
||||||
if (num == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t size = 0;
|
|
||||||
for(int32_t i = 0; i < num; ++i) {
|
|
||||||
SExprInfo* pExpr = taosArrayGetP(pExprList, i);
|
|
||||||
size += pExpr->base.resSchema.bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
SArray* extractFunctionList(SArray* pExprInfoList) {
|
|
||||||
assert(pExprInfoList != NULL);
|
|
||||||
|
|
||||||
size_t len = taosArrayGetSize(pExprInfoList);
|
|
||||||
SArray* p = taosArrayInit(len, POINTER_BYTES);
|
|
||||||
|
|
||||||
for(int32_t i = 0; i < len; ++i) {
|
|
||||||
SExprInfo* pExprInfo = taosArrayGetP(pExprInfoList, i);
|
|
||||||
if (pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE) {
|
|
||||||
char* name = strdup(pExprInfo->pExpr->_function.functionName);
|
|
||||||
taosArrayPush(p, &name);
|
|
||||||
} else {
|
|
||||||
char* name = strdup("project");
|
|
||||||
taosArrayPush(p, &name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tscHasColumnFilter(SQueryStmtInfo* pQueryInfo) {
|
|
||||||
// filter on primary timestamp column
|
|
||||||
if (pQueryInfo->window.skey != INT64_MIN || pQueryInfo->window.ekey != INT64_MAX) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = taosArrayGetSize(pQueryInfo->colList);
|
|
||||||
for (int32_t i = 0; i < size; ++i) {
|
|
||||||
SColumn* pCol = taosArrayGetP(pQueryInfo->colList, i);
|
|
||||||
if (pCol->info.flist.numOfFilters > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t getExprFunctionLevel(const SQueryStmtInfo* pQueryInfo) {
|
|
||||||
int32_t n = 10;
|
|
||||||
|
|
||||||
int32_t level = 0;
|
|
||||||
for(int32_t i = 0; i < n; ++i) {
|
|
||||||
SArray* pList = pQueryInfo->exprList[i];
|
|
||||||
if (taosArrayGetSize(pList) > 0) {
|
|
||||||
level += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return level;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -60,15 +60,12 @@ protected:
|
||||||
return code_;
|
return code_;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVnodeModifOpStmtInfo* reslut() {
|
|
||||||
return res_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dumpReslut() {
|
void dumpReslut() {
|
||||||
size_t num = taosArrayGetSize(res_->pDataBlocks);
|
SVnodeModifOpStmt* pStmt = getVnodeModifStmt(res_);
|
||||||
cout << "schemaAttache:" << (int32_t)res_->schemaAttache << ", payloadType:" << (int32_t)res_->payloadType << ", insertType:" << res_->insertType << ", numOfVgs:" << num << endl;
|
size_t num = taosArrayGetSize(pStmt->pDataBlocks);
|
||||||
|
cout << "schemaAttache:" << (int32_t)pStmt->schemaAttache << ", payloadType:" << (int32_t)pStmt->payloadType << ", insertType:" << pStmt->insertType << ", numOfVgs:" << num << endl;
|
||||||
for (size_t i = 0; i < num; ++i) {
|
for (size_t i = 0; i < num; ++i) {
|
||||||
SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(res_->pDataBlocks, i);
|
SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, i);
|
||||||
cout << "vgId:" << vg->vg.vgId << ", numOfTables:" << vg->numOfTables << ", dataSize:" << vg->size << endl;
|
cout << "vgId:" << vg->vg.vgId << ", numOfTables:" << vg->numOfTables << ", dataSize:" << vg->size << endl;
|
||||||
SSubmitReq* submit = (SSubmitReq*)vg->pData;
|
SSubmitReq* submit = (SSubmitReq*)vg->pData;
|
||||||
cout << "length:" << ntohl(submit->length) << ", numOfBlocks:" << ntohl(submit->numOfBlocks) << endl;
|
cout << "length:" << ntohl(submit->length) << ", numOfBlocks:" << ntohl(submit->numOfBlocks) << endl;
|
||||||
|
@ -84,13 +81,14 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkReslut(int32_t numOfTables, int16_t numOfRows1, int16_t numOfRows2 = -1) {
|
void checkReslut(int32_t numOfTables, int16_t numOfRows1, int16_t numOfRows2 = -1) {
|
||||||
ASSERT_EQ(res_->schemaAttache, 0);
|
SVnodeModifOpStmt* pStmt = getVnodeModifStmt(res_);
|
||||||
ASSERT_EQ(res_->payloadType, PAYLOAD_TYPE_KV);
|
ASSERT_EQ(pStmt->schemaAttache, 0);
|
||||||
ASSERT_EQ(res_->insertType, TSDB_QUERY_TYPE_INSERT);
|
ASSERT_EQ(pStmt->payloadType, PAYLOAD_TYPE_KV);
|
||||||
size_t num = taosArrayGetSize(res_->pDataBlocks);
|
ASSERT_EQ(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
|
||||||
|
size_t num = taosArrayGetSize(pStmt->pDataBlocks);
|
||||||
ASSERT_GE(num, 0);
|
ASSERT_GE(num, 0);
|
||||||
for (size_t i = 0; i < num; ++i) {
|
for (size_t i = 0; i < num; ++i) {
|
||||||
SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(res_->pDataBlocks, i);
|
SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, i);
|
||||||
ASSERT_EQ(vg->numOfTables, numOfTables);
|
ASSERT_EQ(vg->numOfTables, numOfTables);
|
||||||
ASSERT_GE(vg->size, 0);
|
ASSERT_GE(vg->size, 0);
|
||||||
SSubmitReq* submit = (SSubmitReq*)vg->pData;
|
SSubmitReq* submit = (SSubmitReq*)vg->pData;
|
||||||
|
@ -115,7 +113,10 @@ private:
|
||||||
cxt_.pMsg = errMagBuf_;
|
cxt_.pMsg = errMagBuf_;
|
||||||
cxt_.msgLen = max_err_len;
|
cxt_.msgLen = max_err_len;
|
||||||
code_ = TSDB_CODE_SUCCESS;
|
code_ = TSDB_CODE_SUCCESS;
|
||||||
res_ = nullptr;
|
}
|
||||||
|
|
||||||
|
SVnodeModifOpStmt* getVnodeModifStmt(SQuery* pQuery) {
|
||||||
|
return (SVnodeModifOpStmt*)pQuery->pRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
string acctId_;
|
string acctId_;
|
||||||
|
@ -124,7 +125,7 @@ private:
|
||||||
char sqlBuf_[max_sql_len];
|
char sqlBuf_[max_sql_len];
|
||||||
SParseContext cxt_;
|
SParseContext cxt_;
|
||||||
int32_t code_;
|
int32_t code_;
|
||||||
SVnodeModifOpStmtInfo* res_;
|
SQuery* res_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// INSERT INTO tb_name VALUES (field1_value, ...)
|
// INSERT INTO tb_name VALUES (field1_value, ...)
|
||||||
|
|
|
@ -50,19 +50,19 @@ protected:
|
||||||
if (TSDB_CODE_SUCCESS != parseCode) {
|
if (TSDB_CODE_SUCCESS != parseCode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
code = doTranslate(&cxt_, &query_);
|
code = doTranslate(&cxt_, query_);
|
||||||
// cout << "doTranslate return " << code << endl;
|
// cout << "doTranslate return " << code << endl;
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl;
|
cout << "sql:[" << cxt_.pSql << "] code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl;
|
||||||
return (code == translateCode);
|
return (code == translateCode);
|
||||||
}
|
}
|
||||||
if (NULL != query_.pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_.pRoot)) {
|
if (NULL != query_->pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_->pRoot)) {
|
||||||
cout << "input sql : [" << cxt_.pSql << "]" << endl;
|
cout << "input sql : [" << cxt_.pSql << "]" << endl;
|
||||||
// string sql;
|
// string sql;
|
||||||
// selectToSql(query_.pRoot, sql);
|
// selectToSql(query_.pRoot, sql);
|
||||||
// cout << "output sql : [" << sql << "]" << endl;
|
// cout << "output sql : [" << sql << "]" << endl;
|
||||||
string str;
|
string str;
|
||||||
selectToStr(query_.pRoot, str);
|
selectToStr(query_->pRoot, str);
|
||||||
cout << "translate str : \n" << str << endl;
|
cout << "translate str : \n" << str << endl;
|
||||||
}
|
}
|
||||||
return (TSDB_CODE_SUCCESS == translateCode);
|
return (TSDB_CODE_SUCCESS == translateCode);
|
||||||
|
@ -507,7 +507,7 @@ private:
|
||||||
char errMagBuf_[max_err_len];
|
char errMagBuf_[max_err_len];
|
||||||
string sqlBuf_;
|
string sqlBuf_;
|
||||||
SParseContext cxt_;
|
SParseContext cxt_;
|
||||||
SQuery query_;
|
SQuery* query_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(NewParserTest, selectSimple) {
|
TEST_F(NewParserTest, selectSimple) {
|
||||||
|
|
|
@ -1,787 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <function.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include "tglobal.h"
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#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 "os.h"
|
|
||||||
|
|
||||||
#include "astGenerator.h"
|
|
||||||
#include "parserInt.h"
|
|
||||||
#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) {
|
|
||||||
p->colId = colId;
|
|
||||||
p->bytes = bytes;
|
|
||||||
p->type = type;
|
|
||||||
strcpy(p->name, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SCatalogReq* req) {
|
|
||||||
pQueryInfo->numOfTables = 1;
|
|
||||||
|
|
||||||
pQueryInfo->pTableMetaInfo = (STableMetaInfo**)calloc(1, POINTER_BYTES);
|
|
||||||
STableMetaInfo* pTableMetaInfo = (STableMetaInfo*)calloc(1, sizeof(STableMetaInfo));
|
|
||||||
pQueryInfo->pTableMetaInfo[0] = pTableMetaInfo;
|
|
||||||
|
|
||||||
SName* name = (SName*)taosArrayGet(req->pTableName, 0);
|
|
||||||
|
|
||||||
memcpy(&pTableMetaInfo->name, taosArrayGet(req->pTableName, 0), sizeof(SName));
|
|
||||||
pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 6 * sizeof(SSchema));
|
|
||||||
strcpy(pTableMetaInfo->aliasName, name->tname);
|
|
||||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
|
||||||
pTableMeta->tableType = TSDB_NORMAL_TABLE;
|
|
||||||
pTableMeta->tableInfo.numOfColumns = 6;
|
|
||||||
pTableMeta->tableInfo.rowSize = 28;
|
|
||||||
pTableMeta->uid = 110;
|
|
||||||
|
|
||||||
pTableMetaInfo->tagColList = (SArray*)taosArrayInit(4, POINTER_BYTES);
|
|
||||||
|
|
||||||
SSchema* pSchema = pTableMetaInfo->pTableMeta->schema;
|
|
||||||
setSchema(&pSchema[0], TSDB_DATA_TYPE_TIMESTAMP, 8, "ts", 0);
|
|
||||||
setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1);
|
|
||||||
setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2);
|
|
||||||
setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3);
|
|
||||||
setSchema(&pSchema[4], TSDB_DATA_TYPE_BINARY, 12, "c", 4);
|
|
||||||
setSchema(&pSchema[5], TSDB_DATA_TYPE_BINARY, 44, "d", 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sqlCheck(const char* sql, bool valid) {
|
|
||||||
SSqlInfo info1 = doGenerateAST(sql);
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
} else {
|
|
||||||
ASSERT_NE(ret, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST(testCase, validateAST_test) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select a a1111, a+b + 22, tbname from `t.1abc` where ts<now+2h and `col` < 20 + 99");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_INT);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1111");
|
|
||||||
ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->info.colId, 1);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "a1111");
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
|
||||||
|
|
||||||
SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, 1);
|
|
||||||
ASSERT_EQ(p2->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p2->base.numOfParams, 1); // it is the serialized binary string of expression.
|
|
||||||
ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
ASSERT_STRCASEEQ(p2->base.resSchema.name, "a+b + 22");
|
|
||||||
|
|
||||||
// ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a");
|
|
||||||
// ASSERT_EQ(p1->base.colInfo.colId, 1);
|
|
||||||
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
|
||||||
ASSERT_STRCASEEQ(p2->base.token, "a+b + 22");
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 3);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a)");
|
|
||||||
ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->info.colId, 1);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "count(a)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 8);
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test2) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "abc");
|
|
||||||
ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->info.colId, 1);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "count(a)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 8);
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test3) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 6);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_TIMESTAMP);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)");
|
|
||||||
ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.ts");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->info.colId, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "first(ts)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 24);
|
|
||||||
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 6);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test4) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select block_dist() as a1 from `t.1abc`");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
|
||||||
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
|
|
||||||
// ASSERT_EQ(p1->base.colInfo.colId, 0);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_UDC);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "block_dist()");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 0);
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test5) {
|
|
||||||
// todo select concat(concat(a, b), concat(b, a)) from `t.1abc`;
|
|
||||||
|
|
||||||
SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
|
|
||||||
ASSERT_EQ(p1->base.numOfCols, 2);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
|
||||||
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP);
|
|
||||||
ASSERT_STREQ(p1->base.pColumns->name, "sum(a)");
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 0);
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test10) {
|
|
||||||
sqlCheck("select c from `t.1abc`", true);
|
|
||||||
sqlCheck("select length(c) from `t.1abc`", true);
|
|
||||||
sqlCheck("select length(sum(col)) from `t.1abc`", true);
|
|
||||||
sqlCheck("select sum(length(a+b)) from `t.1abc`", true);
|
|
||||||
sqlCheck("select sum(sum(a+b)) from `t.1abc`", false);
|
|
||||||
sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true);
|
|
||||||
sqlCheck("select length(sum(a) + sum(b)) + length(sum(a) + sum(b)) from `t.1abc`", true);
|
|
||||||
sqlCheck("select sum(length(sum(a))) from `t.1abc`", true);
|
|
||||||
sqlCheck("select cov(a, b) from `t.1abc`", true);
|
|
||||||
sqlCheck("select sum(length(a) + count(b)) from `t.1abc`", false);
|
|
||||||
|
|
||||||
sqlCheck("select concat(sum(a), count(b)) from `t.1abc`", true);
|
|
||||||
|
|
||||||
sqlCheck("select concat(concat(a,b), concat(a,b)) from `t.1abc`", true);
|
|
||||||
sqlCheck("select length(length(length(a))) from `t.1abc`", true);
|
|
||||||
sqlCheck("select count() from `t.1abc`", false);
|
|
||||||
sqlCheck("select block_dist() from `t.1abc`", true);
|
|
||||||
sqlCheck("select block_dist(a) from `t.1abc`", false);
|
|
||||||
sqlCheck("select count(*) from `t.1abc` interval(1s) group by a", false);
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
sqlCheck("select length119(a,b) from `t.1abc`", false);
|
|
||||||
sqlCheck("select length(a, b) from `t.1abc`", false);
|
|
||||||
sqlCheck("select block_dist() + 20 from `t.1abc`", true);
|
|
||||||
sqlCheck("select count(b), c from `t.1abc`", false);
|
|
||||||
sqlCheck("select top(a, 20), count(b) from `t.1abc`", false);
|
|
||||||
sqlCheck("select top(a, 20), b from `t.1abc`", false);
|
|
||||||
sqlCheck("select top(a, 20), a+20 from `t.1abc`", true);
|
|
||||||
// sqlCheck("select top(a, 20), bottom(a, 10) from `t.1abc`", false);
|
|
||||||
// sqlCheck("select last_row(*), count(b) from `t.1abc`", false);
|
|
||||||
// sqlCheck("select last_row(a, b) + 20 from `t.1abc`", false);
|
|
||||||
// sqlCheck("select last_row(count(*)) from `t.1abc`", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test6) {
|
|
||||||
SSqlInfo info1 = doGenerateAST(
|
|
||||||
"select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
if (tsCompatibleModel) {
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 6);
|
|
||||||
} else {
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t index = tsCompatibleModel? 1:0;
|
|
||||||
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, index);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 16);
|
|
||||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
|
|
||||||
ASSERT_STRCASEEQ(p1->pExpr->_function.functionName, "sum");
|
|
||||||
ASSERT_EQ(p1->pExpr->_function.num, 1);
|
|
||||||
|
|
||||||
tExprNode* pParam = p1->pExpr->_function.pChild[0];
|
|
||||||
|
|
||||||
ASSERT_EQ(pParam->nodeType, TEXPR_COL_NODE);
|
|
||||||
ASSERT_STREQ(pParam->pSchema->name, "t.1abc.a+b");
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
|
||||||
|
|
||||||
int32_t numOfResCol = tsCompatibleModel? 6:5;
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfResCol);
|
|
||||||
|
|
||||||
index = tsCompatibleModel? 2:1;
|
|
||||||
SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, index);
|
|
||||||
ASSERT_EQ(p2->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p2->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)");
|
|
||||||
|
|
||||||
ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_TMP);
|
|
||||||
ASSERT_STREQ(p2->base.pColumns->name, "t.1abc.b*a");
|
|
||||||
|
|
||||||
ASSERT_STRCASEEQ(p2->base.token, "first(b*a)");
|
|
||||||
ASSERT_EQ(p2->base.interBytes, 24);
|
|
||||||
ASSERT_EQ(p2->pExpr->nodeType, TEXPR_FUNCTION_NODE);
|
|
||||||
ASSERT_STRCASEEQ(p2->pExpr->_function.functionName, "first");
|
|
||||||
ASSERT_EQ(p2->pExpr->_function.num, 1);
|
|
||||||
ASSERT_EQ(p2->pExpr->_function.pChild[0]->nodeType, TEXPR_COL_NODE);
|
|
||||||
ASSERT_STREQ(p2->pExpr->_function.pChild[0]->pSchema->name, "t.1abc.b*a");
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test7) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select count(a+b),count(1) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
|
||||||
|
|
||||||
int32_t index = tsCompatibleModel? 1:0;
|
|
||||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, index);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a+b)");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "count(a+b)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 8);
|
|
||||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
|
|
||||||
ASSERT_STREQ(p1->pExpr->_function.functionName, "count");
|
|
||||||
|
|
||||||
tExprNode* pParam = p1->pExpr->_function.pChild[0];
|
|
||||||
ASSERT_EQ(pParam->nodeType, TEXPR_COL_NODE);
|
|
||||||
|
|
||||||
SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pQueryInfo->exprList[1], 0);
|
|
||||||
ASSERT_EQ(p2->pExpr->nodeType, TEXPR_BINARYEXPR_NODE);
|
|
||||||
|
|
||||||
ASSERT_EQ(p2->pExpr->_node.optr, OP_TYPE_ADD);
|
|
||||||
ASSERT_EQ(p2->pExpr->_node.pLeft->nodeType, TEXPR_COL_NODE);
|
|
||||||
ASSERT_EQ(p2->pExpr->_node.pRight->nodeType, TEXPR_COL_NODE);
|
|
||||||
|
|
||||||
ASSERT_EQ(pParam->pSchema->colId, p2->base.resSchema.colId);
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
|
||||||
|
|
||||||
int32_t numOfCols = tsCompatibleModel? 3:2;
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfCols);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, function_Test8) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), 2);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 16);
|
|
||||||
|
|
||||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
|
|
||||||
ASSERT_STRCASEEQ(p1->pExpr->_function.functionName, "top");
|
|
||||||
ASSERT_TRUE(p1->pExpr->_function.num == 1);
|
|
||||||
|
|
||||||
tExprNode* pParam = p1->pExpr->_function.pChild[0];
|
|
||||||
|
|
||||||
ASSERT_EQ(pParam->nodeType, TSDB_COL_TMP);
|
|
||||||
// ASSERT_EQ(pParam->.optr, TSDB_BINARY_OP_DIVIDE);
|
|
||||||
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE);
|
|
||||||
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE);
|
|
||||||
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
info1 = doGenerateAST("select sum(length(a)+length(b)) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, invalid_sql_Test) {
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlInfo info1 = doGenerateAST("select count(k) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
ctx.db = "db1";
|
|
||||||
ctx.acctId = 1;
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_NE(ret, 0);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
//===============================================================================================================
|
|
||||||
info1 = doGenerateAST("select top(a*b, ABC) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_NE(ret, 0);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&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);
|
|
||||||
|
|
||||||
SParseContext ct= {.requestId = 1, .acctId = 1, .db = "abc", .pTransporter = NULL};
|
|
||||||
SDclStmtInfo* output = qParserValidateDclSqlNode(&info1, &ct, msg, buf.len);
|
|
||||||
ASSERT_NE(output, nullptr);
|
|
||||||
|
|
||||||
// convert the show command to be the select query
|
|
||||||
// select name, privilege, create_time, account from information_schema.users;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(isDclSqlStatement(&info1), true);
|
|
||||||
|
|
||||||
SParseContext ct= {.requestId = 1, .acctId = 1, .db = "abc"};
|
|
||||||
SDclStmtInfo* output = qParserValidateDclSqlNode(&info1, &ct, msg, buf.len);
|
|
||||||
ASSERT_NE(output, nullptr);
|
|
||||||
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
|
|
@ -1,209 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <function.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <tglobal.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#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 "os.h"
|
|
||||||
|
|
||||||
#include "astGenerator.h"
|
|
||||||
#include "parserInt.h"
|
|
||||||
#include "taos.h"
|
|
||||||
#include "tdef.h"
|
|
||||||
#include "tvariant.h"
|
|
||||||
#include "planner.h"
|
|
||||||
#include "../../planner/inc/plannerInt.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
void setSchema(SSchema* p, int32_t type, int32_t bytes, const char* name, int32_t colId) {
|
|
||||||
p->colId = colId;
|
|
||||||
p->bytes = bytes;
|
|
||||||
p->type = type;
|
|
||||||
strcpy(p->name, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SCatalogReq *req) {
|
|
||||||
pQueryInfo->numOfTables = 1;
|
|
||||||
|
|
||||||
pQueryInfo->pTableMetaInfo = (STableMetaInfo**)calloc(1, POINTER_BYTES);
|
|
||||||
STableMetaInfo* pTableMetaInfo = (STableMetaInfo*)calloc(1, sizeof(STableMetaInfo));
|
|
||||||
pQueryInfo->pTableMetaInfo[0] = pTableMetaInfo;
|
|
||||||
|
|
||||||
SName* name = (SName*)taosArrayGet(req->pTableName, 0);
|
|
||||||
|
|
||||||
memcpy(&pTableMetaInfo->name, taosArrayGet(req->pTableName, 0), sizeof(SName));
|
|
||||||
pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 4 * sizeof(SSchema));
|
|
||||||
strcpy(pTableMetaInfo->aliasName, name->tname);
|
|
||||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
|
||||||
pTableMeta->tableType = TSDB_NORMAL_TABLE;
|
|
||||||
pTableMeta->tableInfo.numOfColumns = 4;
|
|
||||||
pTableMeta->tableInfo.rowSize = 28;
|
|
||||||
pTableMeta->uid = 110;
|
|
||||||
|
|
||||||
pTableMetaInfo->tagColList = (SArray*) taosArrayInit(4, POINTER_BYTES);
|
|
||||||
|
|
||||||
SSchema* pSchema = pTableMetaInfo->pTableMeta->schema;
|
|
||||||
setSchema(&pSchema[0], TSDB_DATA_TYPE_TIMESTAMP, 8, "ts", 0);
|
|
||||||
setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1);
|
|
||||||
setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2);
|
|
||||||
setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void generateLogicplan(const char* sql) {
|
|
||||||
SSqlInfo info1 = doGenerateAST(sql);
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
struct SQueryPlanNode* n = nullptr;
|
|
||||||
code = createQueryPlan((const SQueryNode*)pQueryInfo, &n);
|
|
||||||
|
|
||||||
char* str = NULL;
|
|
||||||
queryPlanToString(n, &str);
|
|
||||||
|
|
||||||
printf("--------SQL:%s\n", sql);
|
|
||||||
printf("%s\n", str);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, planner_test) {
|
|
||||||
SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)");
|
|
||||||
ASSERT_EQ(info1.valid, true);
|
|
||||||
|
|
||||||
char msg[128] = {0};
|
|
||||||
SMsgBuf buf;
|
|
||||||
buf.len = 128;
|
|
||||||
buf.buf = msg;
|
|
||||||
|
|
||||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0);
|
|
||||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
|
||||||
ASSERT_EQ(code, 0);
|
|
||||||
|
|
||||||
SCatalogReq req = {0};
|
|
||||||
SParseContext ctx = {0};
|
|
||||||
|
|
||||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
|
||||||
setTableMetaInfo(pQueryInfo, &req);
|
|
||||||
|
|
||||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0);
|
|
||||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
|
||||||
ASSERT_EQ(ret, 0);
|
|
||||||
|
|
||||||
SArray* pExprList = pQueryInfo->exprList[0];
|
|
||||||
|
|
||||||
int32_t num = tsCompatibleModel? 2:1;
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pExprList), num);
|
|
||||||
|
|
||||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
|
||||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
|
||||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
|
||||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
|
|
||||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP);
|
|
||||||
ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
|
|
||||||
ASSERT_EQ(p1->base.interBytes, 16);
|
|
||||||
|
|
||||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
|
|
||||||
ASSERT_STREQ(p1->pExpr->_function.functionName, "top");
|
|
||||||
|
|
||||||
tExprNode* pParam = p1->pExpr->_function.pChild[0];
|
|
||||||
|
|
||||||
ASSERT_EQ(pParam->nodeType, TEXPR_COL_NODE);
|
|
||||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
|
||||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
|
|
||||||
|
|
||||||
struct SQueryPlanNode* n = nullptr;
|
|
||||||
code = createQueryPlan((const SQueryNode*)pQueryInfo, &n);
|
|
||||||
|
|
||||||
char* str = NULL;
|
|
||||||
queryPlanToString(n, &str);
|
|
||||||
printf("%s\n", str);
|
|
||||||
|
|
||||||
destroyQueryInfo(pQueryInfo);
|
|
||||||
qParserCleanupMetaRequestInfo(&req);
|
|
||||||
destroySqlInfo(&info1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(testCase, displayPlan) {
|
|
||||||
generateLogicplan("select count(*) from `t.1abc`");
|
|
||||||
generateLogicplan("select count(*)+ 22 from `t.1abc`");
|
|
||||||
generateLogicplan("select count(*)+ 22 from `t.1abc` interval(1h, 20s) sliding(10m) limit 20,30");
|
|
||||||
generateLogicplan("select count(*) from `t.1abc` group by a");
|
|
||||||
generateLogicplan("select count(A+B) from `t.1abc` group by a");
|
|
||||||
generateLogicplan("select count(length(a)+b) from `t.1abc` group by a");
|
|
||||||
generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s)");
|
|
||||||
generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s) order by 1 desc ");
|
|
||||||
generateLogicplan("select count(*),sum(a),avg(b),min(a+b)+99 from `t.1abc`");
|
|
||||||
generateLogicplan("select count(*), min(a) + 99 from `t.1abc`");
|
|
||||||
generateLogicplan("select count(length(count(*) + 22)) from `t.1abc`");
|
|
||||||
generateLogicplan("select concat(concat(a,b), concat(a,b)) from `t.1abc` limit 20");
|
|
||||||
generateLogicplan("select count(*), first(a), last(b) from `t.1abc` state_window(a)");
|
|
||||||
generateLogicplan("select count(*), first(a), last(b) from `t.1abc` session(ts, 20s)");
|
|
||||||
|
|
||||||
// order by + group by column + limit offset
|
|
||||||
generateLogicplan("select top(a, 20) k from `t.1abc` order by k asc limit 3 offset 1");
|
|
||||||
|
|
||||||
// fill
|
|
||||||
generateLogicplan("select min(a) from `t.1abc` where ts>now and ts<now+2h interval(1s) fill(linear)");
|
|
||||||
|
|
||||||
// union + union all
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// join
|
|
||||||
|
|
||||||
// Aggregate(count(*) [count(*) #5056], sum(a) [sum(a) #5057], avg(b) [avg(b) #5058], min(a+b) [min(a+b) #5060])
|
|
||||||
// Projection(cols: [a+b #5059]) filters:(nil)
|
|
||||||
// Projection(cols: [ts #0], [a #1], [b #2]) filters:(nil)
|
|
||||||
// TableScan(t.1abc #110) time_range: -9223372036854775808 - 9223372036854775807
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -723,4 +725,6 @@ TEST(testCase, extractMeta_test) {
|
||||||
destroySqlInfo(&info1);
|
destroySqlInfo(&info1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_PLANNER_INT_H_
|
|
||||||
#define _TD_PLANNER_INT_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "tarray.h"
|
|
||||||
#include "planner.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "tmsg.h"
|
|
||||||
|
|
||||||
#define QNODE_TAGSCAN 1
|
|
||||||
#define QNODE_TABLESCAN 2
|
|
||||||
#define QNODE_STREAMSCAN 3
|
|
||||||
#define QNODE_PROJECT 4
|
|
||||||
#define QNODE_AGGREGATE 5
|
|
||||||
#define QNODE_GROUPBY 6
|
|
||||||
#define QNODE_LIMIT 7
|
|
||||||
#define QNODE_JOIN 8
|
|
||||||
#define QNODE_DISTINCT 9
|
|
||||||
#define QNODE_SORT 10
|
|
||||||
#define QNODE_UNION 11
|
|
||||||
#define QNODE_TIMEWINDOW 12
|
|
||||||
#define QNODE_SESSIONWINDOW 13
|
|
||||||
#define QNODE_STATEWINDOW 14
|
|
||||||
#define QNODE_FILL 15
|
|
||||||
#define QNODE_MODIFY 16
|
|
||||||
|
|
||||||
typedef struct SQueryDistPlanNodeInfo {
|
|
||||||
bool stableQuery; // super table query or not
|
|
||||||
int32_t phase; // merge|partial
|
|
||||||
int32_t type; // operator type
|
|
||||||
char *name; // operator name
|
|
||||||
SEpSet *sourceEp; // data source epset
|
|
||||||
} SQueryDistPlanNodeInfo;
|
|
||||||
|
|
||||||
typedef struct SQueryTableInfo {
|
|
||||||
char *tableName; // to be deleted
|
|
||||||
uint64_t uid; // to be deleted
|
|
||||||
STableMetaInfo *pMeta;
|
|
||||||
STimeWindow window;
|
|
||||||
} SQueryTableInfo;
|
|
||||||
|
|
||||||
typedef struct SQueryPlanNode {
|
|
||||||
SQueryNodeBasicInfo info;
|
|
||||||
SSchema *pSchema; // the schema of the input SSDatablock
|
|
||||||
int32_t numOfCols; // number of input columns
|
|
||||||
SArray *pExpr; // the query functions or sql aggregations
|
|
||||||
int32_t numOfExpr; // number of result columns, which is also the number of pExprs
|
|
||||||
void *pExtInfo; // additional information
|
|
||||||
// children operator to generated result for current node to process
|
|
||||||
// in case of join, multiple prev nodes exist.
|
|
||||||
SArray *pChildren; // upstream nodes
|
|
||||||
struct SQueryPlanNode *pParent;
|
|
||||||
} SQueryPlanNode;
|
|
||||||
|
|
||||||
typedef struct SDataPayloadInfo {
|
|
||||||
int32_t msgType;
|
|
||||||
SArray *payload;
|
|
||||||
} SDataPayloadInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optimize the query execution plan, currently not implement yet.
|
|
||||||
* @param pQueryNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t optimizeQueryPlan(struct SQueryPlanNode* pQueryNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the query plan according to the bound AST, which is in the form of pQueryInfo
|
|
||||||
* @param pQueryInfo
|
|
||||||
* @param pQueryNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t createQueryPlan(const SQueryNode* pNode, struct SQueryPlanNode** pQueryPlan);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the query plan to string, in order to display it in the shell.
|
|
||||||
* @param pQueryNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t queryPlanToString(struct SQueryPlanNode* pQueryNode, char** str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore the SQL statement according to the logic query plan.
|
|
||||||
* @param pQueryNode
|
|
||||||
* @param sql
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32_t queryPlanToSql(struct SQueryPlanNode* pQueryNode, char** sql);
|
|
||||||
|
|
||||||
int32_t createDag(SQueryPlanNode* pQueryNode, struct SCatalog* pCatalog, SQueryDag** pDag, SArray* pNodeList, uint64_t requestId);
|
|
||||||
void setSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource);
|
|
||||||
int32_t subPlanToString(const SSubplan *pPhyNode, char** str, int32_t* len);
|
|
||||||
int32_t stringToSubplan(const char* str, SSubplan** subplan);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy the query plan object.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void destroyQueryPlan(struct SQueryPlanNode* pQueryNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy the physical plan.
|
|
||||||
* @param pQueryPhyNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void* destroyQueryPhyPlan(struct SPhyNode* pQueryPhyNode);
|
|
||||||
|
|
||||||
const char* opTypeToOpName(int32_t type);
|
|
||||||
int32_t opNameToOpType(const char* name);
|
|
||||||
|
|
||||||
const char* dsinkTypeToDsinkName(int32_t type);
|
|
||||||
int32_t dsinkNameToDsinkType(const char* name);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*_TD_PLANNER_INT_H_*/
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_PLANNERUTIL_H
|
|
||||||
#define TDENGINE_PLANNERUTIL_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TDENGINE_PLANNERUTIL_H
|
|
|
@ -13,6 +13,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include <function.h>
|
#include <function.h>
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
@ -664,3 +666,5 @@ int32_t queryPlanToString(struct SQueryPlanNode* pQueryNode, char** str) {
|
||||||
SQueryPlanNode* queryPlanFromString() {
|
SQueryPlanNode* queryPlanFromString() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "plannerInt.h"
|
#include "plannerInt.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
@ -488,3 +490,5 @@ void qDestroySubplan(SSubplan* pSubplan) {
|
||||||
|
|
||||||
tfree(pSubplan);
|
tfree(pSubplan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "plannerInt.h"
|
#include "plannerInt.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
@ -1221,3 +1223,5 @@ SQueryDag* qStringToDag(const char* pStr) {
|
||||||
cJSON* pRoot = cJSON_Parse(pStr);
|
cJSON* pRoot = cJSON_Parse(pStr);
|
||||||
return qJsonToDag(pRoot);
|
return qJsonToDag(pRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -13,90 +13,32 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "parser.h"
|
#include "planner.h"
|
||||||
#include "plannerInt.h"
|
|
||||||
|
|
||||||
static void extractResSchema(struct SQueryDag* const* pDag, SSchema** pResSchema, int32_t* numOfCols);
|
int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan) {
|
||||||
|
|
||||||
void qDestroyQueryDag(struct SQueryDag* pDag) {
|
|
||||||
if (pDag == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = taosArrayGetSize(pDag->pSubplans);
|
|
||||||
for(size_t i = 0; i < size; ++i) {
|
|
||||||
SArray* pa = taosArrayGetP(pDag->pSubplans, i);
|
|
||||||
|
|
||||||
size_t t = taosArrayGetSize(pa);
|
|
||||||
for(int32_t j = 0; j < t; ++j) {
|
|
||||||
SSubplan* pSubplan = taosArrayGetP(pa, j);
|
|
||||||
qDestroySubplan(pSubplan);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayDestroy(pa);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosArrayDestroy(pDag->pSubplans);
|
|
||||||
tfree(pDag);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t qCreateQueryDag(const struct SQueryNode* pNode, struct SQueryDag** pDag, SSchema** pResSchema, int32_t* numOfCols, SArray* pNodeList,
|
|
||||||
uint64_t requestId) {
|
|
||||||
SQueryPlanNode* pLogicPlan;
|
|
||||||
int32_t code = createQueryPlan(pNode, &pLogicPlan);
|
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
|
||||||
destroyQueryPlan(pLogicPlan);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pLogicPlan->info.type != QNODE_MODIFY) {
|
|
||||||
char* str = NULL;
|
|
||||||
queryPlanToString(pLogicPlan, &str);
|
|
||||||
qDebug("reqId:0x%"PRIx64": %s", requestId, str);
|
|
||||||
tfree(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
code = optimizeQueryPlan(pLogicPlan);
|
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
|
||||||
destroyQueryPlan(pLogicPlan);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = createDag(pLogicPlan, NULL, pDag, pNodeList, requestId);
|
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
|
||||||
destroyQueryPlan(pLogicPlan);
|
|
||||||
qDestroyQueryDag(*pDag);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
extractResSchema(pDag, pResSchema, numOfCols);
|
|
||||||
|
|
||||||
destroyQueryPlan(pLogicPlan);
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract the final result schema
|
|
||||||
void extractResSchema(struct SQueryDag* const* pDag, SSchema** pResSchema, int32_t* numOfCols) {
|
|
||||||
SArray* pTopSubplan = taosArrayGetP((*pDag)->pSubplans, 0);
|
|
||||||
|
|
||||||
SSubplan* pPlan = taosArrayGetP(pTopSubplan, 0);
|
|
||||||
SDataBlockSchema* pDataBlockSchema = &(pPlan->pDataSink->schema);
|
|
||||||
|
|
||||||
*numOfCols = pDataBlockSchema->numOfCols;
|
|
||||||
if (*numOfCols > 0) {
|
|
||||||
*pResSchema = calloc(pDataBlockSchema->numOfCols, sizeof(SSchema));
|
|
||||||
memcpy((*pResSchema), pDataBlockSchema->pSchema, pDataBlockSchema->numOfCols * sizeof(SSchema));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qSetSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource) {
|
void qSetSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource) {
|
||||||
setSubplanExecutionNode(subplan, templateId, pSource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t qSubPlanToString(const SSubplan *subplan, char** str, int32_t* len) {
|
int32_t qSubPlanToString(const SSubplan* subplan, char** str, int32_t* len) {
|
||||||
return subPlanToString(subplan, str, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t qStringToSubplan(const char* str, SSubplan** subplan) {
|
int32_t qStringToSubplan(const char* str, SSubplan** subplan) {
|
||||||
return stringToSubplan(str, subplan);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char* qQueryPlanToString(const SQueryPlan* pPlan) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SQueryPlan* qStringToQueryPlan(const char* pStr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void qDestroyQueryPlan(SQueryPlan* pPlan) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "plannerImpl.h"
|
#include "plannerImpl.h"
|
||||||
|
|
||||||
#include "functionMgt.h"
|
#include "functionMgt.h"
|
||||||
|
#include "query.h"
|
||||||
|
|
||||||
#define CHECK_ALLOC(p, res) \
|
#define CHECK_ALLOC(p, res) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -33,13 +35,13 @@
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
typedef struct SPlanContext {
|
typedef struct SLogicPlanContext {
|
||||||
int32_t errCode;
|
int32_t errCode;
|
||||||
int32_t planNodeId;
|
int32_t planNodeId;
|
||||||
} SPlanContext;
|
} SLogicPlanContext;
|
||||||
|
|
||||||
static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt);
|
static SLogicNode* createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt);
|
||||||
static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable);
|
static SLogicNode* createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable);
|
||||||
|
|
||||||
typedef struct SRewriteExprCxt {
|
typedef struct SRewriteExprCxt {
|
||||||
int32_t errCode;
|
int32_t errCode;
|
||||||
|
@ -109,7 +111,7 @@ static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pEx
|
||||||
return cxt.errCode;
|
return cxt.errCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* pushLogicNode(SPlanContext* pCxt, SLogicNode* pRoot, SLogicNode* pNode) {
|
static SLogicNode* pushLogicNode(SLogicPlanContext* pCxt, SLogicNode* pRoot, SLogicNode* pNode) {
|
||||||
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +140,7 @@ error:
|
||||||
return pRoot;
|
return pRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) {
|
static SLogicNode* createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) {
|
||||||
SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN);
|
SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN);
|
||||||
CHECK_ALLOC(pScan, NULL);
|
CHECK_ALLOC(pScan, NULL);
|
||||||
pScan->node.id = pCxt->planNodeId++;
|
pScan->node.id = pCxt->planNodeId++;
|
||||||
|
@ -166,7 +168,7 @@ static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
|
||||||
return (SLogicNode*)pScan;
|
return (SLogicNode*)pScan;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) {
|
static SLogicNode* createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) {
|
||||||
SLogicNode* pRoot = createQueryLogicNode(pCxt, pTable->pSubquery);
|
SLogicNode* pRoot = createQueryLogicNode(pCxt, pTable->pSubquery);
|
||||||
CHECK_ALLOC(pRoot, NULL);
|
CHECK_ALLOC(pRoot, NULL);
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
|
@ -176,7 +178,7 @@ static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSel
|
||||||
return pRoot;
|
return pRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) {
|
static SLogicNode* createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) {
|
||||||
SJoinLogicNode* pJoin = (SJoinLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN);
|
SJoinLogicNode* pJoin = (SJoinLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN);
|
||||||
CHECK_ALLOC(pJoin, NULL);
|
CHECK_ALLOC(pJoin, NULL);
|
||||||
pJoin->node.id = pCxt->planNodeId++;
|
pJoin->node.id = pCxt->planNodeId++;
|
||||||
|
@ -209,7 +211,7 @@ static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
|
||||||
return (SLogicNode*)pJoin;
|
return (SLogicNode*)pJoin;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable) {
|
static SLogicNode* createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable) {
|
||||||
switch (nodeType(pTable)) {
|
switch (nodeType(pTable)) {
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable);
|
return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable);
|
||||||
|
@ -255,7 +257,7 @@ static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
|
||||||
return DEAL_RES_CONTINUE;
|
return DEAL_RES_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
|
static SNodeList* createColumnByRewriteExps(SLogicPlanContext* pCxt, SNodeList* pExprs) {
|
||||||
SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() };
|
SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() };
|
||||||
CHECK_ALLOC(cxt.pList, NULL);
|
CHECK_ALLOC(cxt.pList, NULL);
|
||||||
|
|
||||||
|
@ -267,7 +269,7 @@ static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExpr
|
||||||
return cxt.pList;
|
return cxt.pList;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
static SLogicNode* createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
|
||||||
SNodeList* pAggFuncs = NULL;
|
SNodeList* pAggFuncs = NULL;
|
||||||
CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL);
|
CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL);
|
||||||
if (NULL == pAggFuncs && NULL == pSelect->pGroupByList) {
|
if (NULL == pAggFuncs && NULL == pSelect->pGroupByList) {
|
||||||
|
@ -314,7 +316,7 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect)
|
||||||
return (SLogicNode*)pAgg;
|
return (SLogicNode*)pAgg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNodeList* createColumnByProjections(SPlanContext* pCxt, SNodeList* pExprs) {
|
static SNodeList* createColumnByProjections(SLogicPlanContext* pCxt, SNodeList* pExprs) {
|
||||||
SNodeList* pList = nodesMakeList();
|
SNodeList* pList = nodesMakeList();
|
||||||
CHECK_ALLOC(pList, NULL);
|
CHECK_ALLOC(pList, NULL);
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
|
@ -336,7 +338,7 @@ error:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
static SLogicNode* createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
|
||||||
SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
|
SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
|
||||||
CHECK_ALLOC(pProject, NULL);
|
CHECK_ALLOC(pProject, NULL);
|
||||||
pProject->node.id = pCxt->planNodeId++;
|
pProject->node.id = pCxt->planNodeId++;
|
||||||
|
@ -349,7 +351,7 @@ static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSele
|
||||||
return (SLogicNode*)pProject;
|
return (SLogicNode*)pProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
static SLogicNode* createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
|
||||||
SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable);
|
SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable);
|
||||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && NULL != pSelect->pWhere) {
|
if (TSDB_CODE_SUCCESS == pCxt->errCode && NULL != pSelect->pWhere) {
|
||||||
pRoot->pConditions = nodesCloneNode(pSelect->pWhere);
|
pRoot->pConditions = nodesCloneNode(pSelect->pWhere);
|
||||||
|
@ -364,7 +366,7 @@ static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelec
|
||||||
return pRoot;
|
return pRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
|
static SLogicNode* createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt) {
|
||||||
switch (nodeType(pStmt)) {
|
switch (nodeType(pStmt)) {
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt);
|
return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt);
|
||||||
|
@ -374,7 +376,7 @@ static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
|
int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
|
||||||
SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1 };
|
SLogicPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1 };
|
||||||
SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
|
SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
|
||||||
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||||
nodesDestroyNode((SNode*)pRoot);
|
nodesDestroyNode((SNode*)pRoot);
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#include "tvariant.h"
|
|
||||||
#include "plannerUtil.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "plannerImpl.h"
|
#include "plannerImpl.h"
|
||||||
#include "newParser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
@ -46,17 +46,17 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool run(TestTarget target = TEST_PHYSICAL_PLAN) {
|
bool run(TestTarget target = TEST_PHYSICAL_PLAN) {
|
||||||
int32_t code = parser(&cxt_, &query_);
|
int32_t code = qParseQuerySql(&cxt_, &query_);
|
||||||
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] parser code:" << code << ", strerror:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
cout << "sql:[" << cxt_.pSql << "] parser code:" << code << ", strerror:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string syntaxTreeStr = toString(query_.pRoot, false);
|
const string syntaxTreeStr = toString(query_->pRoot, false);
|
||||||
|
|
||||||
SLogicNode* pLogicPlan = nullptr;
|
SLogicNode* pLogicPlan = nullptr;
|
||||||
code = createLogicPlan(query_.pRoot, &pLogicPlan);
|
code = createLogicPlan(query_->pRoot, &pLogicPlan);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] logic plan code:" << code << ", strerror:" << tstrerror(code) << endl;
|
cout << "sql:[" << cxt_.pSql << "] logic plan code:" << code << ", strerror:" << tstrerror(code) << endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -110,7 +110,7 @@ private:
|
||||||
char errMagBuf_[max_err_len];
|
char errMagBuf_[max_err_len];
|
||||||
string sqlBuf_;
|
string sqlBuf_;
|
||||||
SParseContext cxt_;
|
SParseContext cxt_;
|
||||||
SQuery query_;
|
SQuery* query_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(NewPlannerTest, simple) {
|
TEST_F(NewPlannerTest, simple) {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "plannerInt.h"
|
#include "plannerInt.h"
|
||||||
|
@ -205,3 +205,4 @@ TEST_F(PhyPlanTest, insertTest) {
|
||||||
SQueryDag* dag = result();
|
SQueryDag* dag = result();
|
||||||
// todo check
|
// todo check
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -53,7 +53,7 @@ TEST(testCase, planner_test) {
|
||||||
char msg[128] = {0};
|
char msg[128] = {0};
|
||||||
const char* sql = "select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)";
|
const char* sql = "select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)";
|
||||||
|
|
||||||
SQueryStmtInfo* pQueryInfo = nullptr;
|
// SQueryStmtInfo* pQueryInfo = nullptr;
|
||||||
// int32_t code = qParseQuerySql(sql, strlen(sql), &pQueryInfo, 0, msg, sizeof(msg));
|
// int32_t code = qParseQuerySql(sql, strlen(sql), &pQueryInfo, 0, msg, sizeof(msg));
|
||||||
// ASSERT_EQ(code, 0);
|
// ASSERT_EQ(code, 0);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(qworker
|
target_link_libraries(qworker
|
||||||
PRIVATE os util transport planner qcom executor
|
PRIVATE os util transport nodes planner qcom executor
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${BUILD_TEST})
|
if(${BUILD_TEST})
|
||||||
|
|
|
@ -8,7 +8,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
||||||
ADD_EXECUTABLE(qworkerTest ${SOURCE_LIST})
|
ADD_EXECUTABLE(qworkerTest ${SOURCE_LIST})
|
||||||
TARGET_LINK_LIBRARIES(
|
TARGET_LINK_LIBRARIES(
|
||||||
qworkerTest
|
qworkerTest
|
||||||
PUBLIC os util common transport gtest qcom planner qworker executor
|
PUBLIC os util common transport gtest qcom nodes planner qworker executor
|
||||||
)
|
)
|
||||||
|
|
||||||
TARGET_INCLUDE_DIRECTORIES(
|
TARGET_INCLUDE_DIRECTORIES(
|
||||||
|
|
|
@ -9,7 +9,7 @@ target_include_directories(
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
scheduler
|
scheduler
|
||||||
PUBLIC os util planner qcom common catalog transport
|
PUBLIC os util nodes planner qcom common catalog transport
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${BUILD_TEST})
|
if(${BUILD_TEST})
|
||||||
|
|
|
@ -303,7 +303,7 @@ int32_t schRecordTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *ad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32_t schValidateAndBuildJob(SQueryDag *pDag, SSchJob *pJob) {
|
int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) {
|
||||||
int32_t code = 0;
|
int32_t code = 0;
|
||||||
pJob->queryId = pDag->queryId;
|
pJob->queryId = pDag->queryId;
|
||||||
|
|
||||||
|
@ -1283,7 +1283,7 @@ void schDropJobAllTasks(SSchJob *pJob) {
|
||||||
schDropTaskInHashList(pJob, pJob->failTasks);
|
schDropTaskInHashList(pJob, pJob->failTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryDag* pDag, struct SSchJob** job, const char* sql, bool syncSchedule) {
|
static int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryPlan* pDag, struct SSchJob** job, const char* sql, bool syncSchedule) {
|
||||||
qDebug("QID:0x%"PRIx64" job started", pDag->queryId);
|
qDebug("QID:0x%"PRIx64" job started", pDag->queryId);
|
||||||
|
|
||||||
if (pNodeList == NULL || (pNodeList && taosArrayGetSize(pNodeList) <= 0)) {
|
if (pNodeList == NULL || (pNodeList && taosArrayGetSize(pNodeList) <= 0)) {
|
||||||
|
@ -1398,7 +1398,7 @@ int32_t schedulerInit(SSchedulerCfg *cfg) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, struct SSchJob** pJob, const char* sql, SQueryResult *pRes) {
|
int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryPlan* pDag, struct SSchJob** pJob, const char* sql, SQueryResult *pRes) {
|
||||||
if (NULL == transport || NULL == pDag || NULL == pDag->pSubplans || NULL == pJob || NULL == pRes) {
|
if (NULL == transport || NULL == pDag || NULL == pDag->pSubplans || NULL == pJob || NULL == pRes) {
|
||||||
SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1410,7 @@ int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, str
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryDag* pDag, const char* sql, struct SSchJob** pJob) {
|
int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryPlan* pDag, const char* sql, struct SSchJob** pJob) {
|
||||||
if (NULL == transport || NULL == pDag || NULL == pDag->pSubplans || NULL == pJob) {
|
if (NULL == transport || NULL == pDag || NULL == pDag->pSubplans || NULL == pJob) {
|
||||||
SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
}
|
}
|
||||||
|
@ -1419,7 +1419,7 @@ int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryDag* pDa
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t schedulerConvertDagToTaskList(SQueryDag* pDag, SArray **pTasks) {
|
int32_t schedulerConvertDagToTaskList(SQueryPlan* pDag, SArray **pTasks) {
|
||||||
if (NULL == pDag || pDag->numOfSubplans <= 0 || taosArrayGetSize(pDag->pSubplans) == 0) {
|
if (NULL == pDag || pDag->numOfSubplans <= 0 || taosArrayGetSize(pDag->pSubplans) == 0) {
|
||||||
SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ void schtInitLogFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void schtBuildQueryDag(SQueryDag *dag) {
|
void schtBuildQueryDag(SQueryPlan *dag) {
|
||||||
uint64_t qId = schtQueryId;
|
uint64_t qId = schtQueryId;
|
||||||
|
|
||||||
dag->queryId = qId;
|
dag->queryId = qId;
|
||||||
|
@ -97,7 +97,7 @@ void schtBuildQueryDag(SQueryDag *dag) {
|
||||||
scanPlan->pChildren = NULL;
|
scanPlan->pChildren = NULL;
|
||||||
scanPlan->level = 1;
|
scanPlan->level = 1;
|
||||||
scanPlan->pParents = taosArrayInit(1, POINTER_BYTES);
|
scanPlan->pParents = taosArrayInit(1, POINTER_BYTES);
|
||||||
scanPlan->pNode = (SPhyNode*)calloc(1, sizeof(SPhyNode));
|
scanPlan->pNode = (SPhysiNode*)calloc(1, sizeof(SPhysiNode));
|
||||||
scanPlan->msgType = TDMT_VND_QUERY;
|
scanPlan->msgType = TDMT_VND_QUERY;
|
||||||
|
|
||||||
mergePlan->id.queryId = qId;
|
mergePlan->id.queryId = qId;
|
||||||
|
@ -109,7 +109,7 @@ void schtBuildQueryDag(SQueryDag *dag) {
|
||||||
|
|
||||||
mergePlan->pChildren = taosArrayInit(1, POINTER_BYTES);
|
mergePlan->pChildren = taosArrayInit(1, POINTER_BYTES);
|
||||||
mergePlan->pParents = NULL;
|
mergePlan->pParents = NULL;
|
||||||
mergePlan->pNode = (SPhyNode*)calloc(1, sizeof(SPhyNode));
|
mergePlan->pNode = (SPhysiNode*)calloc(1, sizeof(SPhysiNode));
|
||||||
mergePlan->msgType = TDMT_VND_QUERY;
|
mergePlan->msgType = TDMT_VND_QUERY;
|
||||||
|
|
||||||
SSubplan *mergePointer = (SSubplan *)taosArrayPush(merge, &mergePlan);
|
SSubplan *mergePointer = (SSubplan *)taosArrayPush(merge, &mergePlan);
|
||||||
|
@ -122,12 +122,12 @@ void schtBuildQueryDag(SQueryDag *dag) {
|
||||||
taosArrayPush(dag->pSubplans, &scan);
|
taosArrayPush(dag->pSubplans, &scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void schtFreeQueryDag(SQueryDag *dag) {
|
void schtFreeQueryDag(SQueryPlan *dag) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void schtBuildInsertDag(SQueryDag *dag) {
|
void schtBuildInsertDag(SQueryPlan *dag) {
|
||||||
uint64_t qId = 0x0000000000000002;
|
uint64_t qId = 0x0000000000000002;
|
||||||
|
|
||||||
dag->queryId = qId;
|
dag->queryId = qId;
|
||||||
|
@ -150,7 +150,7 @@ void schtBuildInsertDag(SQueryDag *dag) {
|
||||||
insertPlan[0].pChildren = NULL;
|
insertPlan[0].pChildren = NULL;
|
||||||
insertPlan[0].pParents = NULL;
|
insertPlan[0].pParents = NULL;
|
||||||
insertPlan[0].pNode = NULL;
|
insertPlan[0].pNode = NULL;
|
||||||
insertPlan[0].pDataSink = (SDataSink*)calloc(1, sizeof(SDataSink));
|
insertPlan[0].pDataSink = (SDataSinkNode*)calloc(1, sizeof(SDataSinkNode));
|
||||||
insertPlan[0].msgType = TDMT_VND_SUBMIT;
|
insertPlan[0].msgType = TDMT_VND_SUBMIT;
|
||||||
|
|
||||||
insertPlan[1].id.queryId = qId;
|
insertPlan[1].id.queryId = qId;
|
||||||
|
@ -166,7 +166,7 @@ void schtBuildInsertDag(SQueryDag *dag) {
|
||||||
insertPlan[1].pChildren = NULL;
|
insertPlan[1].pChildren = NULL;
|
||||||
insertPlan[1].pParents = NULL;
|
insertPlan[1].pParents = NULL;
|
||||||
insertPlan[1].pNode = NULL;
|
insertPlan[1].pNode = NULL;
|
||||||
insertPlan[1].pDataSink = (SDataSink*)calloc(1, sizeof(SDataSink));
|
insertPlan[1].pDataSink = (SDataSinkNode*)calloc(1, sizeof(SDataSinkNode));
|
||||||
insertPlan[1].msgType = TDMT_VND_SUBMIT;
|
insertPlan[1].msgType = TDMT_VND_SUBMIT;
|
||||||
|
|
||||||
taosArrayPush(inserta, &insertPlan);
|
taosArrayPush(inserta, &insertPlan);
|
||||||
|
@ -347,7 +347,7 @@ void* schtRunJobThread(void *aa) {
|
||||||
char *dbname = "1.db1";
|
char *dbname = "1.db1";
|
||||||
char *tablename = "table1";
|
char *tablename = "table1";
|
||||||
SVgroupInfo vgInfo = {0};
|
SVgroupInfo vgInfo = {0};
|
||||||
SQueryDag dag = {0};
|
SQueryPlan dag = {0};
|
||||||
|
|
||||||
schtInitLogFile();
|
schtInitLogFile();
|
||||||
|
|
||||||
|
@ -517,7 +517,7 @@ TEST(queryTest, normalCase) {
|
||||||
char *tablename = "table1";
|
char *tablename = "table1";
|
||||||
SVgroupInfo vgInfo = {0};
|
SVgroupInfo vgInfo = {0};
|
||||||
SSchJob *pJob = NULL;
|
SSchJob *pJob = NULL;
|
||||||
SQueryDag dag = {0};
|
SQueryPlan dag = {0};
|
||||||
|
|
||||||
schtInitLogFile();
|
schtInitLogFile();
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ TEST(insertTest, normalCase) {
|
||||||
char *dbname = "1.db1";
|
char *dbname = "1.db1";
|
||||||
char *tablename = "table1";
|
char *tablename = "table1";
|
||||||
SVgroupInfo vgInfo = {0};
|
SVgroupInfo vgInfo = {0};
|
||||||
SQueryDag dag = {0};
|
SQueryPlan dag = {0};
|
||||||
uint64_t numOfRows = 0;
|
uint64_t numOfRows = 0;
|
||||||
|
|
||||||
schtInitLogFile();
|
schtInitLogFile();
|
||||||
|
|
Loading…
Reference in New Issue