Merge pull request #10031 from taosdata/feature/3.0_wxy
TD-13197 SELECT statement syntax definition
This commit is contained in:
commit
09071e70eb
|
@ -86,6 +86,7 @@ tests/comparisonTest/opentsdb/opentsdbtest/.settings/
|
|||
tests/examples/JDBC/JDBCDemo/.classpath
|
||||
tests/examples/JDBC/JDBCDemo/.project
|
||||
tests/examples/JDBC/JDBCDemo/.settings/
|
||||
source/libs/parser/inc/new_sql.*
|
||||
|
||||
# Emacs
|
||||
# -*- mode: gitignore; -*-
|
||||
|
@ -101,4 +102,4 @@ TAGS
|
|||
|
||||
contrib/*
|
||||
!contrib/CMakeLists.txt
|
||||
!contrib/test
|
||||
!contrib/test
|
||||
|
|
|
@ -207,6 +207,36 @@
|
|||
#define TK_INTO 189
|
||||
#define TK_VALUES 190
|
||||
|
||||
#define NEW_TK_UNION 1
|
||||
#define NEW_TK_ALL 2
|
||||
#define NEW_TK_MINUS 3
|
||||
#define NEW_TK_EXCEPT 4
|
||||
#define NEW_TK_INTERSECT 5
|
||||
#define NEW_TK_NK_PLUS 6
|
||||
#define NEW_TK_NK_MINUS 7
|
||||
#define NEW_TK_NK_STAR 8
|
||||
#define NEW_TK_NK_SLASH 9
|
||||
#define NEW_TK_SHOW 10
|
||||
#define NEW_TK_DATABASES 11
|
||||
#define NEW_TK_NK_ID 12
|
||||
#define NEW_TK_NK_LP 13
|
||||
#define NEW_TK_NK_RP 14
|
||||
#define NEW_TK_NK_COMMA 15
|
||||
#define NEW_TK_NK_LITERAL 16
|
||||
#define NEW_TK_NK_DOT 17
|
||||
#define NEW_TK_SELECT 18
|
||||
#define NEW_TK_DISTINCT 19
|
||||
#define NEW_TK_AS 20
|
||||
#define NEW_TK_FROM 21
|
||||
#define NEW_TK_WITH 22
|
||||
#define NEW_TK_RECURSIVE 23
|
||||
#define NEW_TK_ORDER 24
|
||||
#define NEW_TK_BY 25
|
||||
#define NEW_TK_ASC 26
|
||||
#define NEW_TK_DESC 27
|
||||
#define NEW_TK_NULLS 28
|
||||
#define NEW_TK_FIRST 29
|
||||
#define NEW_TK_LAST 30
|
||||
|
||||
#define TK_SPACE 300
|
||||
#define TK_COMMENT 301
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct SQueryNode {
|
|||
int16_t type;
|
||||
} SQueryNode;
|
||||
|
||||
#define nodeType(nodeptr) (((const SQueryNode*)(nodeptr))->type)
|
||||
#define queryNodeType(nodeptr) (((const SQueryNode*)(nodeptr))->type)
|
||||
|
||||
typedef struct SField {
|
||||
char name[TSDB_COL_NAME_LEN];
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "tarray.h"
|
||||
#include "tdef.h"
|
||||
|
||||
typedef enum ENodeType {
|
||||
|
@ -35,12 +34,14 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_JOIN_TABLE,
|
||||
QUERY_NODE_GROUPING_SET,
|
||||
QUERY_NODE_ORDER_BY_EXPR,
|
||||
QUERY_NODE_LIMIT,
|
||||
QUERY_NODE_STATE_WINDOW,
|
||||
QUERY_NODE_SESSION_WINDOW,
|
||||
QUERY_NODE_INTERVAL_WINDOW,
|
||||
|
||||
QUERY_NODE_SET_OPERATOR,
|
||||
QUERY_NODE_SELECT_STMT
|
||||
QUERY_NODE_SELECT_STMT,
|
||||
QUERY_NODE_SHOW_STMT
|
||||
} ENodeType;
|
||||
|
||||
/**
|
||||
|
@ -52,6 +53,27 @@ typedef struct SNode {
|
|||
} SNode;
|
||||
|
||||
#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type)
|
||||
#define setNodeType(nodeptr, type) (((SNode*)(nodeptr))->type = (type))
|
||||
|
||||
typedef struct SListCell {
|
||||
SNode* pNode;
|
||||
struct SListCell* pNext;
|
||||
} SListCell;
|
||||
|
||||
typedef struct SNodeList {
|
||||
int16_t length;
|
||||
SListCell* pHeader;
|
||||
} SNodeList;
|
||||
|
||||
#define LIST_LENGTH(l) (NULL != (l) ? (l)->length : 0)
|
||||
|
||||
#define FOREACH(node, list) \
|
||||
for (SListCell* cell = (NULL != (list) ? (list)->pHeader : NULL); (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext)
|
||||
|
||||
#define FORBOTH(node1, list1, node2, list2) \
|
||||
for (SListCell* cell1 = (NULL != (list1) ? (list1)->pHeader : NULL), *cell2 = (NULL != (list2) ? (list2)->pHeader : NULL); \
|
||||
(NULL == cell1 ? (node1 = NULL, false) : (node1 = cell1->pNode, true)), (NULL == cell2 ? (node2 = NULL, false) : (node2 = cell2->pNode, true)), (node1 != NULL && node2 != NULL); \
|
||||
cell1 = cell1->pNext, cell2 = cell2->pNext)
|
||||
|
||||
typedef struct SDataType {
|
||||
uint8_t type;
|
||||
|
@ -128,7 +150,7 @@ typedef enum ELogicConditionType {
|
|||
typedef struct SLogicConditionNode {
|
||||
ENodeType type; // QUERY_NODE_LOGIC_CONDITION
|
||||
ELogicConditionType condType;
|
||||
SArray* pParameterList;
|
||||
SNodeList* pParameterList;
|
||||
} SLogicConditionNode;
|
||||
|
||||
typedef struct SIsNullCondNode {
|
||||
|
@ -141,7 +163,7 @@ typedef struct SFunctionNode {
|
|||
SExprNode type; // QUERY_NODE_FUNCTION
|
||||
char functionName[TSDB_FUNC_NAME_LEN];
|
||||
int32_t funcId;
|
||||
SArray* pParameterList; // SNode
|
||||
SNodeList* pParameterList; // SNode
|
||||
} SFunctionNode;
|
||||
|
||||
typedef struct STableNode {
|
||||
|
@ -151,12 +173,12 @@ typedef struct STableNode {
|
|||
} STableNode;
|
||||
|
||||
typedef struct SRealTableNode {
|
||||
STableNode type; // QUERY_NODE_REAL_TABLE
|
||||
STableNode table; // QUERY_NODE_REAL_TABLE
|
||||
char dbName[TSDB_DB_NAME_LEN];
|
||||
} SRealTableNode;
|
||||
|
||||
typedef struct STempTableNode {
|
||||
STableNode type; // QUERY_NODE_TEMP_TABLE
|
||||
STableNode table; // QUERY_NODE_TEMP_TABLE
|
||||
SNode* pSubquery;
|
||||
} STempTableNode;
|
||||
|
||||
|
@ -165,7 +187,7 @@ typedef enum EJoinType {
|
|||
} EJoinType;
|
||||
|
||||
typedef struct SJoinTableNode {
|
||||
STableNode type; // QUERY_NODE_JOIN_TABLE
|
||||
STableNode table; // QUERY_NODE_JOIN_TABLE
|
||||
EJoinType joinType;
|
||||
SNode* pLeft;
|
||||
SNode* pRight;
|
||||
|
@ -179,7 +201,7 @@ typedef enum EGroupingSetType {
|
|||
typedef struct SGroupingSetNode {
|
||||
ENodeType type; // QUERY_NODE_GROUPING_SET
|
||||
EGroupingSetType groupingSetType;
|
||||
SArray* pParameterList;
|
||||
SNodeList* pParameterList;
|
||||
} SGroupingSetNode;
|
||||
|
||||
typedef enum EOrder {
|
||||
|
@ -188,7 +210,8 @@ typedef enum EOrder {
|
|||
} EOrder;
|
||||
|
||||
typedef enum ENullOrder {
|
||||
NULL_ORDER_FIRST = 1,
|
||||
NULL_ORDER_DEFAULT = 1,
|
||||
NULL_ORDER_FIRST,
|
||||
NULL_ORDER_LAST
|
||||
} ENullOrder;
|
||||
|
||||
|
@ -199,10 +222,11 @@ typedef struct SOrderByExprNode {
|
|||
ENullOrder nullOrder;
|
||||
} SOrderByExprNode;
|
||||
|
||||
typedef struct SLimitInfo {
|
||||
typedef struct SLimitNode {
|
||||
ENodeType type; // QUERY_NODE_LIMIT
|
||||
uint64_t limit;
|
||||
uint64_t offset;
|
||||
} SLimitInfo;
|
||||
} SLimitNode;
|
||||
|
||||
typedef struct SStateWindowNode {
|
||||
ENodeType type; // QUERY_NODE_STATE_WINDOW
|
||||
|
@ -225,15 +249,16 @@ typedef struct SIntervalWindowNode {
|
|||
typedef struct SSelectStmt {
|
||||
ENodeType type; // QUERY_NODE_SELECT_STMT
|
||||
bool isDistinct;
|
||||
SArray* pProjectionList; // SNode
|
||||
bool isStar;
|
||||
SNodeList* pProjectionList; // SNode
|
||||
SNode* pFromTable;
|
||||
SNode* pWhereCond;
|
||||
SArray* pPartitionByList; // SNode
|
||||
SNodeList* pPartitionByList; // SNode
|
||||
SNode* pWindowClause;
|
||||
SArray* pGroupByList; // SGroupingSetNode
|
||||
SArray* pOrderByList; // SOrderByExprNode
|
||||
SLimitInfo limit;
|
||||
SLimitInfo slimit;
|
||||
SNodeList* pGroupByList; // SGroupingSetNode
|
||||
SNodeList* pOrderByList; // SOrderByExprNode
|
||||
SLimitNode limit;
|
||||
SLimitNode slimit;
|
||||
} SSelectStmt;
|
||||
|
||||
typedef enum ESetOperatorType {
|
||||
|
@ -249,20 +274,24 @@ typedef struct SSetOperator {
|
|||
|
||||
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
|
||||
|
||||
bool nodeArrayWalker(SArray* pArray, FQueryNodeWalker walker, void* pContext);
|
||||
bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext);
|
||||
bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext);
|
||||
bool nodesWalkNodeList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext);
|
||||
|
||||
bool stmtWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext);
|
||||
bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext);
|
||||
|
||||
bool nodeEqual(const SNode* a, const SNode* b);
|
||||
bool nodesEqualNode(const SNode* a, const SNode* b);
|
||||
|
||||
void cloneNode(const SNode* pNode);
|
||||
void nodesCloneNode(const SNode* pNode);
|
||||
|
||||
int32_t nodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
|
||||
int32_t stringToNode(const char* pStr, SNode** pNode);
|
||||
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
|
||||
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
||||
|
||||
bool isTimeorderQuery(const SNode* pQuery);
|
||||
bool isTimelineQuery(const SNode* pQuery);
|
||||
bool nodesIsTimeorderQuery(const SNode* pQuery);
|
||||
bool nodesIsTimelineQuery(const SNode* pQuery);
|
||||
|
||||
SNode* nodesMakeNode(ENodeType type);
|
||||
void nodesDestroyNode(SNode* pNode);
|
||||
void nodesDestroyNodeList(SNodeList* pList);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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_NODES_SHOW_STMTS_H_
|
||||
#define _TD_NODES_SHOW_STMTS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nodes.h"
|
||||
|
||||
typedef enum EShowStmtType {
|
||||
SHOW_TYPE_DATABASE = 1
|
||||
} EShowStmtType;
|
||||
|
||||
typedef struct SShowStmt {
|
||||
ENodeType type; // QUERY_NODE_SHOW_STMT
|
||||
EShowStmtType showType;
|
||||
} SShowStmt;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_NODES_SHOW_STMTS_H_*/
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
|||
|
||||
target_link_libraries(
|
||||
parser
|
||||
PRIVATE os util catalog function transport qcom
|
||||
PRIVATE os util nodes catalog function transport qcom
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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_AST_CREATER_H_
|
||||
#define _TD_AST_CREATER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nodes.h"
|
||||
#include "parser.h"
|
||||
|
||||
typedef struct SAstCreateContext {
|
||||
SParseContext* pQueryCxt;
|
||||
bool notSupport;
|
||||
bool valid;
|
||||
SNode* pRootNode;
|
||||
} SAstCreateContext;
|
||||
|
||||
int32_t createAstCreateContext(const SParseContext* pQueryCxt, SAstCreateContext* pCxt);
|
||||
int32_t destroyAstCreateContext(SAstCreateContext* pCxt);
|
||||
|
||||
void* acquireRaii(SAstCreateContext* pCxt, void* p);
|
||||
void* releaseRaii(SAstCreateContext* pCxt, void* p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_AST_CREATER_H_*/
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 "nodes.h"
|
||||
#include "nodesShowStmts.h"
|
||||
#include "astCreateContext.h"
|
||||
#include "ttoken.h"
|
||||
|
||||
#ifndef _TD_AST_CREATE_FUNCS_H_
|
||||
#define _TD_AST_CREATE_FUNCS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool checkTableName(const SToken* pTableName);
|
||||
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode);
|
||||
SNode* addOrderByList(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrderByList);
|
||||
SNode* addSlimit(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit);
|
||||
SNode* addLimit(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit);
|
||||
SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableName, const SToken* pColumnName);
|
||||
SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset);
|
||||
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode);
|
||||
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder);
|
||||
SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName);
|
||||
SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable);
|
||||
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight);
|
||||
SNode* createShowStmt(SAstCreateContext* pCxt, EShowStmtType type);
|
||||
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_AST_CREATE_FUNCS_H_*/
|
|
@ -0,0 +1,199 @@
|
|||
//lemon parser file to generate sql parse by using finite-state-machine code used to parse sql
|
||||
//usage: lemon sql.y
|
||||
|
||||
%name NewParse
|
||||
|
||||
%token_prefix NEW_TK_
|
||||
%token_type { SToken }
|
||||
%default_type { SNode* }
|
||||
%default_destructor { nodesDestroyNode($$); }
|
||||
|
||||
%extra_argument { SAstCreateContext* pCxt }
|
||||
|
||||
%include {
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nodes.h"
|
||||
#include "ttoken.h"
|
||||
#include "ttokendef.h"
|
||||
#include "astCreateFuncs.h"
|
||||
|
||||
#define PARSER_TRACE printf("rule = %s\n", yyRuleName[yyruleno])
|
||||
}
|
||||
|
||||
%syntax_error {
|
||||
if(TOKEN.z) {
|
||||
char msg[] = "syntax error near \"%s\"";
|
||||
int32_t sqlLen = strlen(&TOKEN.z[0]);
|
||||
|
||||
if (sqlLen + sizeof(msg)/sizeof(msg[0]) + 1 > pCxt->pQueryCxt->msgLen) {
|
||||
char tmpstr[128] = {0};
|
||||
memcpy(tmpstr, &TOKEN.z[0], sizeof(tmpstr)/sizeof(tmpstr[0]) - 1);
|
||||
sprintf(pCxt->pQueryCxt->pMsg, msg, tmpstr);
|
||||
} else {
|
||||
sprintf(pCxt->pQueryCxt->pMsg, msg, &TOKEN.z[0]);
|
||||
}
|
||||
} else {
|
||||
sprintf(pCxt->pQueryCxt->pMsg, "Incomplete SQL statement");
|
||||
}
|
||||
pCxt->valid = false;
|
||||
}
|
||||
|
||||
%parse_accept { printf("parsing complete!\n" );}
|
||||
|
||||
//%left OR.
|
||||
//%left AND.
|
||||
//%right NOT.
|
||||
%left UNION ALL MINUS EXCEPT INTERSECT.
|
||||
//%left EQ NE ISNULL NOTNULL IS LIKE MATCH NMATCH GLOB BETWEEN IN.
|
||||
//%left GT GE LT LE.
|
||||
//%left BITAND BITOR LSHIFT RSHIFT.
|
||||
%left NK_PLUS NK_MINUS.
|
||||
//%left DIVIDE TIMES.
|
||||
%left NK_STAR NK_SLASH. //REM.
|
||||
//%left CONCAT.
|
||||
//%right UMINUS UPLUS BITNOT.
|
||||
|
||||
cmd ::= SHOW DATABASES. { PARSER_TRACE; createShowStmt(pCxt, SHOW_TYPE_DATABASE); }
|
||||
|
||||
cmd ::= query_expression(A). { PARSER_TRACE; pCxt->pRootNode = A; }
|
||||
|
||||
//////////////////////// value_function /////////////////////////////////
|
||||
value_function ::= NK_ID NK_LP value_expression NK_RP.
|
||||
value_function ::= NK_ID NK_LP value_expression NK_COMMA value_expression NK_RP.
|
||||
|
||||
//////////////////////// value_expression_primary /////////////////////////////////
|
||||
value_expression_primary ::= NK_LP value_expression NK_RP.
|
||||
value_expression_primary ::= nonparenthesized_value_expression_primary.
|
||||
|
||||
nonparenthesized_value_expression_primary ::= literal.
|
||||
// ?
|
||||
nonparenthesized_value_expression_primary ::= column_reference.
|
||||
|
||||
literal ::= NK_LITERAL.
|
||||
|
||||
column_reference(A) ::= NK_ID(B). { PARSER_TRACE; A = createColumnNode(pCxt, NULL, &B); }
|
||||
column_reference(A) ::= table_name(B) NK_DOT NK_ID(C). { PARSER_TRACE; A = createColumnNode(pCxt, &B, &C); }
|
||||
|
||||
//////////////////////// value_expression /////////////////////////////////
|
||||
value_expression ::= common_value_expression.
|
||||
|
||||
common_value_expression ::= numeric_value_expression.
|
||||
|
||||
numeric_value_expression ::= numeric_primary.
|
||||
numeric_value_expression ::= NK_PLUS numeric_primary.
|
||||
numeric_value_expression ::= NK_MINUS numeric_primary.
|
||||
numeric_value_expression ::= numeric_value_expression NK_PLUS numeric_value_expression.
|
||||
numeric_value_expression ::= numeric_value_expression NK_MINUS numeric_value_expression.
|
||||
numeric_value_expression ::= numeric_value_expression NK_STAR numeric_value_expression.
|
||||
numeric_value_expression ::= numeric_value_expression NK_SLASH numeric_value_expression.
|
||||
|
||||
numeric_primary ::= value_expression_primary.
|
||||
numeric_primary ::= value_function.
|
||||
|
||||
//////////////////////// query_specification /////////////////////////////////
|
||||
query_specification(A) ::= SELECT set_quantifier_opt(B) select_list(C) from_clause(D). { PARSER_TRACE; A = createSelectStmt(pCxt, B, C, D); }
|
||||
|
||||
%type set_quantifier_opt { bool }
|
||||
%destructor set_quantifier_opt {}
|
||||
set_quantifier_opt(A) ::= . { PARSER_TRACE; A = false; }
|
||||
set_quantifier_opt(A) ::= DISTINCT. { PARSER_TRACE; A = true; }
|
||||
set_quantifier_opt(A) ::= ALL. { PARSER_TRACE; A = false; }
|
||||
|
||||
%type select_list { SNodeList* }
|
||||
%destructor select_list { nodesDestroyNodeList($$); }
|
||||
select_list(A) ::= NK_STAR. { PARSER_TRACE; A = NULL; }
|
||||
select_list(A) ::= select_sublist(B). { PARSER_TRACE; A = B; }
|
||||
|
||||
%type select_sublist { SNodeList* }
|
||||
%destructor select_sublist { nodesDestroyNodeList($$); }
|
||||
select_sublist(A) ::= select_item(B). { PARSER_TRACE; A = createNodeList(pCxt, B); }
|
||||
select_sublist(A) ::= select_sublist(B) NK_COMMA select_item(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, C); }
|
||||
|
||||
select_item(A) ::= value_expression(B). { PARSER_TRACE; A = B; }
|
||||
select_item(A) ::= value_expression(B) AS NK_ID(C). { PARSER_TRACE; A = setProjectionAlias(pCxt, B, &C); }
|
||||
select_item(A) ::= table_name(B) NK_DOT NK_STAR(C). { PARSER_TRACE; A = createColumnNode(pCxt, &B, &C); }
|
||||
|
||||
from_clause(A) ::= FROM table_reference_list(B). { PARSER_TRACE; A = B; }
|
||||
|
||||
//%type table_reference_list { SNodeList* }
|
||||
//%destructor table_reference_list { nodesDestroyNodeList($$); }
|
||||
table_reference_list(A) ::= table_reference(B). { PARSER_TRACE; A = B; }
|
||||
//table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { PARSER_TRACE; A = createJoinTableNode(pCxt, B, C); }
|
||||
|
||||
//table_reference(A) ::= NK_ID(B). { PARSER_TRACE; A = createRealTableNode(pCxt, ); }
|
||||
table_reference(A) ::= table_factor(B). { PARSER_TRACE; A = B; }
|
||||
//table_reference ::= joined_table.
|
||||
|
||||
table_factor(A) ::= table_primary(B). { PARSER_TRACE; A = B; }
|
||||
|
||||
table_primary(A) ::= table_name(B). { PARSER_TRACE; A = createRealTableNode(pCxt, NULL, &B); }
|
||||
table_primary(A) ::= db_name(B) NK_DOT table_name(C). { PARSER_TRACE; A = createRealTableNode(pCxt, &B, &C); }
|
||||
table_primary ::= derived_table.
|
||||
|
||||
derived_table ::= table_subquery.
|
||||
|
||||
%type db_name { SToken }
|
||||
db_name(A) ::= NK_ID(B). { PARSER_TRACE; A = B; }
|
||||
%type table_name { SToken }
|
||||
table_name(A) ::= NK_ID(B). { PARSER_TRACE; A = B; }
|
||||
|
||||
//////////////////////// subquery /////////////////////////////////
|
||||
subquery ::= NK_LR query_expression NK_RP.
|
||||
|
||||
table_subquery ::= subquery.
|
||||
|
||||
// query_expression
|
||||
query_expression(A) ::= with_clause_opt query_expression_body(B) order_by_clause_opt(C) slimit_clause_opt(D) limit_clause_opt(E). {
|
||||
PARSER_TRACE;
|
||||
addOrderByList(pCxt, B, C);
|
||||
addSlimit(pCxt, B, D);
|
||||
addLimit(pCxt, B, E);
|
||||
A = B;
|
||||
}
|
||||
|
||||
// WITH AS
|
||||
with_clause_opt ::= . {}
|
||||
|
||||
query_expression_body(A) ::= query_primary(B). { PARSER_TRACE; A = B; }
|
||||
query_expression_body(A) ::= query_expression_body(B) UNION ALL query_expression_body(D). { PARSER_TRACE; A = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, B, D); }
|
||||
|
||||
query_primary(A) ::= query_specification(B). { PARSER_TRACE; A = B; }
|
||||
query_primary(A) ::= NK_LP query_expression_body(B) order_by_clause_opt limit_clause_opt slimit_clause_opt NK_RP. { PARSER_TRACE; A = B;}
|
||||
|
||||
%type order_by_clause_opt { SNodeList* }
|
||||
%destructor order_by_clause_opt { nodesDestroyNodeList($$); }
|
||||
order_by_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; }
|
||||
order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { PARSER_TRACE; A = B; }
|
||||
|
||||
slimit_clause_opt(A) ::= . { A = NULL; }
|
||||
slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B) SOFFSET NK_INTEGER(C). { A = createLimitNode(pCxt, &B, &C); }
|
||||
slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); }
|
||||
|
||||
limit_clause_opt(A) ::= . { A = NULL; }
|
||||
limit_clause_opt(A) ::= LIMIT NK_INTEGER(B) OFFSET NK_INTEGER(C). { A = createLimitNode(pCxt, &B, &C); }
|
||||
limit_clause_opt(A) ::= LIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); }
|
||||
|
||||
//////////////////////// sort_specification_list /////////////////////////////////
|
||||
%type sort_specification_list { SNodeList* }
|
||||
%destructor sort_specification_list { nodesDestroyNodeList($$); }
|
||||
sort_specification_list(A) ::= sort_specification(B). { PARSER_TRACE; A = createNodeList(pCxt, B); }
|
||||
sort_specification_list(A) ::= sort_specification_list(B) NK_COMMA sort_specification(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, C); }
|
||||
|
||||
sort_specification(A) ::= value_expression(B) ordering_specification_opt(C) null_ordering_opt(D). { PARSER_TRACE; A = createOrderByExprNode(pCxt, B, C, D); }
|
||||
|
||||
%type ordering_specification_opt EOrder
|
||||
%destructor ordering_specification_opt {}
|
||||
ordering_specification_opt(A) ::= . { PARSER_TRACE; A = ORDER_ASC; }
|
||||
ordering_specification_opt(A) ::= ASC. { PARSER_TRACE; A = ORDER_ASC; }
|
||||
ordering_specification_opt(A) ::= DESC. { PARSER_TRACE; A = ORDER_DESC; }
|
||||
|
||||
%type null_ordering_opt ENullOrder
|
||||
%destructor null_ordering_opt {}
|
||||
null_ordering_opt(A) ::= . { PARSER_TRACE; A = NULL_ORDER_DEFAULT; }
|
||||
null_ordering_opt(A) ::= NULLS FIRST. { PARSER_TRACE; A = NULL_ORDER_FIRST; }
|
||||
null_ordering_opt(A) ::= NULLS LAST. { PARSER_TRACE; A = NULL_ORDER_LAST; }
|
|
@ -14,11 +14,23 @@
|
|||
*/
|
||||
|
||||
#include "nodes.h"
|
||||
#include "parser.h"
|
||||
|
||||
int32_t nodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
||||
#ifndef _TD_AST_CREATE_FUNCS_H_
|
||||
#define _TD_AST_CREATE_FUNCS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SQuery {
|
||||
SNode* pRoot;
|
||||
} SQuery;
|
||||
|
||||
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t stringToNode(const char* pStr, SNode** pNode) {
|
||||
|
||||
}
|
||||
#endif /*_TD_AST_CREATE_FUNCS_H_*/
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 "ttoken.h"
|
||||
#include "astCreateContext.h"
|
||||
|
||||
void* acquireRaii(SAstCreateContext* pCxt, void* p) {
|
||||
if (NULL == p) {
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void* releaseRaii(SAstCreateContext* pCxt, void* p) {
|
||||
if (NULL == p) {
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int32_t createAstCreater(const SParseContext* pQueryCxt, SAstCreateContext* pCxt) {
|
||||
|
||||
}
|
||||
|
||||
int32_t destroyAstCreater(SAstCreateContext* pCxt) {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
/*
|
||||
* 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 "astCreateFuncs.h"
|
||||
|
||||
#include "astCreateContext.h"
|
||||
|
||||
bool checkTableName(const SToken* pTableName) {
|
||||
printf("%p : %d, %d, %s\n", pTableName, pTableName->type, pTableName->n, pTableName->z);
|
||||
return pTableName->n < TSDB_TABLE_NAME_LEN ? true : false;
|
||||
}
|
||||
|
||||
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) {
|
||||
|
||||
}
|
||||
|
||||
SNode* addOrderByList(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrderByList) {
|
||||
|
||||
}
|
||||
|
||||
SNode* addSlimit(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit) {
|
||||
|
||||
}
|
||||
|
||||
SNode* addLimit(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit) {
|
||||
|
||||
}
|
||||
|
||||
SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableName, const SToken* pColumnName) {
|
||||
|
||||
}
|
||||
|
||||
SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset) {
|
||||
|
||||
}
|
||||
|
||||
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) {
|
||||
|
||||
}
|
||||
|
||||
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder) {
|
||||
|
||||
}
|
||||
|
||||
SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName) {
|
||||
SRealTableNode* realTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE);
|
||||
if (NULL != pDbName) {
|
||||
printf("DbName %p : %d, %d, %s\n", pDbName, pDbName->type, pDbName->n, pDbName->z);
|
||||
strncpy(realTable->dbName, pDbName->z, pDbName->n);
|
||||
}
|
||||
printf("TableName %p : %d, %d, %s\n", pTableName, pTableName->type, pTableName->n, pTableName->z);
|
||||
strncpy(realTable->table.tableName, pTableName->z, pTableName->n);
|
||||
return acquireRaii(pCxt, realTable);
|
||||
}
|
||||
|
||||
SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable) {
|
||||
SSelectStmt* select = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT);
|
||||
select->isDistinct = isDistinct;
|
||||
if (NULL == pProjectionList) {
|
||||
select->isStar = true;
|
||||
}
|
||||
select->pProjectionList = releaseRaii(pCxt, pProjectionList);
|
||||
printf("pTable = %p, name = %s\n", pTable, ((SRealTableNode*)pTable)->table.tableName);
|
||||
select->pFromTable = releaseRaii(pCxt, pTable);
|
||||
return acquireRaii(pCxt, select);
|
||||
}
|
||||
|
||||
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) {
|
||||
|
||||
}
|
||||
|
||||
SNode* createShowStmt(SAstCreateContext* pCxt, EShowStmtType type) {
|
||||
|
||||
}
|
||||
|
||||
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) {
|
||||
|
||||
}
|
|
@ -13,12 +13,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nodes.h"
|
||||
// int32_t doTranslate() {
|
||||
|
||||
bool isTimeorderQuery(const SNode* pQuery) {
|
||||
|
||||
}
|
||||
|
||||
bool isTimelineQuery(const SNode* pQuery) {
|
||||
|
||||
}
|
||||
// }
|
File diff suppressed because it is too large
Load Diff
|
@ -249,7 +249,7 @@ void qDestroyQuery(SQueryNode* pQueryNode) {
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t type = nodeType(pQueryNode);
|
||||
int32_t type = queryNodeType(pQueryNode);
|
||||
if (type == TSDB_SQL_INSERT || type == TSDB_SQL_CREATE_TABLE) {
|
||||
SVnodeModifOpStmtInfo* pModifInfo = (SVnodeModifOpStmtInfo*)pQueryNode;
|
||||
taosArrayDestroy(pModifInfo->pDataBlocks);
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 "parserImpl.h"
|
||||
|
||||
#include "ttoken.h"
|
||||
#include "astCreateContext.h"
|
||||
|
||||
typedef void* (*FMalloc)(size_t);
|
||||
typedef void (*FFree)(void*);
|
||||
|
||||
extern void* NewParseAlloc(FMalloc);
|
||||
extern void NewParse(void*, int, SToken, void*);
|
||||
extern void NewParseFree(void*, FFree);
|
||||
|
||||
uint32_t toNewTokenId(uint32_t tokenId) {
|
||||
switch (tokenId) {
|
||||
case TK_UNION:
|
||||
return NEW_TK_UNION;
|
||||
case TK_ALL:
|
||||
return NEW_TK_ALL;
|
||||
case TK_MINUS:
|
||||
return NEW_TK_NK_MINUS;
|
||||
case TK_PLUS:
|
||||
return NEW_TK_NK_PLUS;
|
||||
case TK_STAR:
|
||||
return NEW_TK_NK_STAR;
|
||||
case TK_SLASH:
|
||||
return NEW_TK_NK_SLASH;
|
||||
case TK_SHOW:
|
||||
return NEW_TK_SHOW;
|
||||
case TK_DATABASES:
|
||||
return NEW_TK_DATABASES;
|
||||
case TK_ID:
|
||||
return NEW_TK_NK_ID;
|
||||
case TK_LP:
|
||||
return NEW_TK_NK_LP;
|
||||
case TK_RP:
|
||||
return NEW_TK_NK_RP;
|
||||
case TK_COMMA:
|
||||
return NEW_TK_NK_COMMA;
|
||||
case TK_DOT:
|
||||
return NEW_TK_NK_DOT;
|
||||
case TK_SELECT:
|
||||
return NEW_TK_SELECT;
|
||||
case TK_DISTINCT:
|
||||
return NEW_TK_DISTINCT;
|
||||
case TK_AS:
|
||||
return NEW_TK_AS;
|
||||
case TK_FROM:
|
||||
return NEW_TK_FROM;
|
||||
case TK_ORDER:
|
||||
return NEW_TK_ORDER;
|
||||
case TK_BY:
|
||||
return NEW_TK_BY;
|
||||
case TK_ASC:
|
||||
return NEW_TK_ASC;
|
||||
case TK_DESC:
|
||||
return NEW_TK_DESC;
|
||||
}
|
||||
return tokenId;
|
||||
}
|
||||
|
||||
uint32_t getToken(const char* z, uint32_t* tokenId) {
|
||||
uint32_t n = tGetToken(z, tokenId);
|
||||
*tokenId = toNewTokenId(*tokenId);
|
||||
return n;
|
||||
}
|
||||
|
||||
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||
SAstCreateContext cxt = { .pQueryCxt = pParseCxt, .valid = true, .pRootNode = NULL };
|
||||
void *pParser = NewParseAlloc(malloc);
|
||||
int32_t i = 0;
|
||||
while (1) {
|
||||
SToken t0 = {0};
|
||||
printf("===========================\n");
|
||||
if (cxt.pQueryCxt->pSql[i] == 0) {
|
||||
NewParse(pParser, 0, t0, &cxt);
|
||||
goto abort_parse;
|
||||
}
|
||||
printf("input: [%s]\n", cxt.pQueryCxt->pSql + i);
|
||||
t0.n = getToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type);
|
||||
t0.z = (char *)(cxt.pQueryCxt->pSql + i);
|
||||
printf("token %p : %d %d [%s]\n", &t0, t0.type, t0.n, t0.z);
|
||||
i += t0.n;
|
||||
|
||||
switch (t0.type) {
|
||||
case TK_SPACE:
|
||||
case TK_COMMENT: {
|
||||
break;
|
||||
}
|
||||
case TK_SEMI: {
|
||||
NewParse(pParser, 0, t0, &cxt);
|
||||
goto abort_parse;
|
||||
}
|
||||
|
||||
case TK_QUESTION:
|
||||
case TK_ILLEGAL: {
|
||||
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z);
|
||||
cxt.valid = false;
|
||||
goto abort_parse;
|
||||
}
|
||||
|
||||
case TK_HEX:
|
||||
case TK_OCT:
|
||||
case TK_BIN: {
|
||||
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unsupported token: \"%s\"", t0.z);
|
||||
cxt.valid = false;
|
||||
goto abort_parse;
|
||||
}
|
||||
|
||||
default:
|
||||
NewParse(pParser, t0.type, t0, &cxt);
|
||||
if (!cxt.valid) {
|
||||
goto abort_parse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abort_parse:
|
||||
NewParseFree(pParser, free);
|
||||
pQuery->pRoot = cxt.pRootNode;
|
||||
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
|
||||
}
|
|
@ -15,5 +15,5 @@ TARGET_INCLUDE_DIRECTORIES(
|
|||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
parserTest
|
||||
PUBLIC os util common parser catalog transport gtest function planner qcom
|
||||
PUBLIC os util common nodes parser catalog transport gtest function planner qcom
|
||||
)
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include "parserImpl.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
class NewParserTest : public Test {
|
||||
protected:
|
||||
void setDatabase(const string& acctId, const string& db) {
|
||||
acctId_ = acctId;
|
||||
db_ = db;
|
||||
}
|
||||
|
||||
void bind(const char* sql) {
|
||||
reset();
|
||||
cxt_.acctId = atoi(acctId_.c_str());
|
||||
cxt_.db = (char*) db_.c_str();
|
||||
strcpy(sqlBuf_, sql);
|
||||
cxt_.sqlLen = strlen(sql);
|
||||
sqlBuf_[cxt_.sqlLen] = '\0';
|
||||
cxt_.pSql = sqlBuf_;
|
||||
|
||||
}
|
||||
|
||||
int32_t run() {
|
||||
int32_t code = doParse(&cxt_, &query_);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
cout << "code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
||||
return code;
|
||||
}
|
||||
cout << nodeType(query_.pRoot) << endl;
|
||||
if (NULL != query_.pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_.pRoot)) {
|
||||
// SNode* pWhereCond;
|
||||
// SNodeList* pPartitionByList; // SNode
|
||||
// SNode* pWindowClause;
|
||||
// SNodeList* pGroupByList; // SGroupingSetNode
|
||||
// SNodeList* pOrderByList; // SOrderByExprNode
|
||||
// SLimitNode limit;
|
||||
// SLimitNode slimit;
|
||||
|
||||
SSelectStmt* select = (SSelectStmt*)query_.pRoot;
|
||||
string sql("SELECT ");
|
||||
if (select->isDistinct) {
|
||||
sql.append("DISTINCT ");
|
||||
}
|
||||
if (nullptr == select->pProjectionList) {
|
||||
sql.append("* ");
|
||||
} else {
|
||||
nodeListToSql(select->pProjectionList, sql);
|
||||
}
|
||||
sql.append("FROM ");
|
||||
tableToSql(select->pFromTable, sql);
|
||||
cout << sql << endl;
|
||||
}
|
||||
// char* pStr = NULL;
|
||||
// int32_t len = 0;
|
||||
// code = nodesNodeToString(query_.pRoot, &pStr, &len);
|
||||
// if (code != TSDB_CODE_SUCCESS) {
|
||||
// cout << "code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
||||
// return code;
|
||||
// }
|
||||
// cout << "node tree:\n" << pStr << endl;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int max_err_len = 1024;
|
||||
static const int max_sql_len = 1024 * 1024;
|
||||
|
||||
void tableToSql(const SNode* node, string& sql) {
|
||||
const STableNode* table = (const STableNode*)node;
|
||||
cout << "node : " << nodeType(node) << endl;
|
||||
switch (nodeType(node)) {
|
||||
case QUERY_NODE_REAL_TABLE: {
|
||||
SRealTableNode* realTable = (SRealTableNode*)table;
|
||||
if ('\0' != realTable->dbName[0]) {
|
||||
sql.append(realTable->dbName);
|
||||
sql.append(".");
|
||||
}
|
||||
sql.append(realTable->table.tableName);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nodeListToSql(const SNodeList* nodelist, string& sql, const string& seq = ",") {
|
||||
SNode* node = nullptr;
|
||||
bool firstNode = true;
|
||||
FOREACH(node, nodelist) {
|
||||
if (!firstNode) {
|
||||
sql.append(", ");
|
||||
}
|
||||
switch (nodeType(node)) {
|
||||
case QUERY_NODE_COLUMN:
|
||||
sql.append(((SColumnNode*)node)->colName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
memset(&cxt_, 0, sizeof(cxt_));
|
||||
memset(errMagBuf_, 0, max_err_len);
|
||||
cxt_.pMsg = errMagBuf_;
|
||||
cxt_.msgLen = max_err_len;
|
||||
}
|
||||
|
||||
string acctId_;
|
||||
string db_;
|
||||
char errMagBuf_[max_err_len];
|
||||
char sqlBuf_[max_sql_len];
|
||||
SParseContext cxt_;
|
||||
SQuery query_;
|
||||
};
|
||||
|
||||
// SELECT * FROM t1
|
||||
TEST_F(NewParserTest, selectStar) {
|
||||
setDatabase("root", "test");
|
||||
|
||||
bind("SELECT * FROM t1");
|
||||
ASSERT_EQ(run(), TSDB_CODE_SUCCESS);
|
||||
|
||||
bind("SELECT * FROM test.t1");
|
||||
ASSERT_EQ(run(), TSDB_CODE_SUCCESS);
|
||||
}
|
|
@ -74,7 +74,7 @@ int32_t createSelectPlan(const SQueryStmtInfo* pSelect, SQueryPlanNode** pQueryP
|
|||
}
|
||||
|
||||
int32_t createQueryPlan(const SQueryNode* pNode, SQueryPlanNode** pQueryPlan) {
|
||||
switch (nodeType(pNode)) {
|
||||
switch (queryNodeType(pNode)) {
|
||||
case TSDB_SQL_SELECT: {
|
||||
return createSelectPlan((const SQueryStmtInfo*)pNode, pQueryPlan);
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ SArray* createQueryPlanImpl(const SQueryStmtInfo* pQueryInfo) {
|
|||
}
|
||||
|
||||
static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) {
|
||||
int32_t type = nodeType(pQueryNode);
|
||||
int32_t type = queryNodeType(pQueryNode);
|
||||
if (type == QNODE_MODIFY) {
|
||||
SDataPayloadInfo* pInfo = pQueryNode->pExtInfo;
|
||||
|
||||
|
|
|
@ -461,7 +461,7 @@ static void destroyDataSinkNode(SDataSink* pSinkNode) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (nodeType(pSinkNode) == DSINK_Dispatch) {
|
||||
if (queryNodeType(pSinkNode) == DSINK_Dispatch) {
|
||||
SDataDispatcher* pDdSink = (SDataDispatcher*)pSinkNode;
|
||||
tfree(pDdSink->sink.schema.pSchema);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
|
||||
#include "nodes.h"
|
||||
|
||||
void cloneNode(const SNode* pNode) {
|
||||
void nodesCloneNode(const SNode* pNode) {
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 "nodes.h"
|
||||
|
||||
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
||||
switch (nodeType(pNode)) {
|
||||
case QUERY_NODE_COLUMN:
|
||||
case QUERY_NODE_VALUE:
|
||||
case QUERY_NODE_OPERATOR:
|
||||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
case QUERY_NODE_IS_NULL_CONDITION:
|
||||
case QUERY_NODE_FUNCTION:
|
||||
case QUERY_NODE_REAL_TABLE:
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
case QUERY_NODE_JOIN_TABLE:
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
case QUERY_NODE_LIMIT:
|
||||
case QUERY_NODE_STATE_WINDOW:
|
||||
case QUERY_NODE_SESSION_WINDOW:
|
||||
case QUERY_NODE_INTERVAL_WINDOW:
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
case QUERY_NODE_SHOW_STMT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t nodesStringToNode(const char* pStr, SNode** pNode) {
|
||||
|
||||
}
|
|
@ -32,17 +32,17 @@
|
|||
|
||||
#define COMPARE_NODE_FIELD(fldname) \
|
||||
do { \
|
||||
if (!nodeEqual(a->fldname, b->fldname)) \
|
||||
if (!nodesEqualNode(a->fldname, b->fldname)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
#define COMPARE_ARRAY_FIELD(fldname) \
|
||||
#define COMPARE_NODE_LIST_FIELD(fldname) \
|
||||
do { \
|
||||
if (!nodeArrayEqual(a->fldname, b->fldname)) \
|
||||
if (!nodeNodeListEqual(a->fldname, b->fldname)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
static bool nodeArrayEqual(const SArray* a, const SArray* b) {
|
||||
static bool nodeNodeListEqual(const SNodeList* a, const SNodeList* b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
|
@ -51,13 +51,13 @@ static bool nodeArrayEqual(const SArray* a, const SArray* b) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (taosArrayGetSize(a) != taosArrayGetSize(b)) {
|
||||
if (LIST_LENGTH(a) != LIST_LENGTH(b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = taosArrayGetSize(a);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (!nodeEqual((SNode*)taosArrayGetP(a, i), (SNode*)taosArrayGetP(b, i))) {
|
||||
SNode* na, *nb;
|
||||
FORBOTH(na, a, nb, b) {
|
||||
if (!nodesEqualNode(na, nb)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ static bool operatorNodeEqual(const SOperatorNode* a, const SOperatorNode* b) {
|
|||
|
||||
static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicConditionNode* b) {
|
||||
COMPARE_SCALAR_FIELD(condType);
|
||||
COMPARE_ARRAY_FIELD(pParameterList);
|
||||
COMPARE_NODE_LIST_FIELD(pParameterList);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -97,11 +97,11 @@ static bool isNullConditionNodeEqual(const SIsNullCondNode* a, const SIsNullCond
|
|||
|
||||
static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
|
||||
COMPARE_SCALAR_FIELD(funcId);
|
||||
COMPARE_ARRAY_FIELD(pParameterList);
|
||||
COMPARE_NODE_LIST_FIELD(pParameterList);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nodeEqual(const SNode* a, const SNode* b) {
|
||||
bool nodesEqualNode(const SNode* a, const SNode* b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ bool nodeEqual(const SNode* a, const SNode* b) {
|
|||
case QUERY_NODE_JOIN_TABLE:
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
case QUERY_NODE_LIMIT:
|
||||
return false; // todo
|
||||
default:
|
||||
break;
|
|
@ -17,17 +17,17 @@
|
|||
|
||||
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
|
||||
|
||||
bool nodeArrayWalker(SArray* pArray, FQueryNodeWalker walker, void* pContext) {
|
||||
size_t size = taosArrayGetSize(pArray);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (!nodeTreeWalker((SNode*)taosArrayGetP(pArray, i), walker, pContext)) {
|
||||
return false;
|
||||
}
|
||||
bool nodesWalkNodeList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext) {
|
||||
SNode* node;
|
||||
FOREACH(node, pNodeList) {
|
||||
if (!nodesWalkNode(node, walker, pContext)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
|
||||
bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
|
||||
if (NULL == pNode) {
|
||||
return true;
|
||||
}
|
||||
|
@ -39,38 +39,39 @@ bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
|
|||
switch (nodeType(pNode)) {
|
||||
case QUERY_NODE_COLUMN:
|
||||
case QUERY_NODE_VALUE:
|
||||
case QUERY_NODE_LIMIT:
|
||||
// these node types with no subnodes
|
||||
return true;
|
||||
case QUERY_NODE_OPERATOR: {
|
||||
SOperatorNode* pOpNode = (SOperatorNode*)pNode;
|
||||
if (!nodeTreeWalker(pOpNode->pLeft, walker, pContext)) {
|
||||
if (!nodesWalkNode(pOpNode->pLeft, walker, pContext)) {
|
||||
return false;
|
||||
}
|
||||
return nodeTreeWalker(pOpNode->pRight, walker, pContext);
|
||||
return nodesWalkNode(pOpNode->pRight, walker, pContext);
|
||||
}
|
||||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
return nodeArrayWalker(((SLogicConditionNode*)pNode)->pParameterList, walker, pContext);
|
||||
return nodesWalkNodeList(((SLogicConditionNode*)pNode)->pParameterList, walker, pContext);
|
||||
case QUERY_NODE_IS_NULL_CONDITION:
|
||||
return nodeTreeWalker(((SIsNullCondNode*)pNode)->pExpr, walker, pContext);
|
||||
return nodesWalkNode(((SIsNullCondNode*)pNode)->pExpr, walker, pContext);
|
||||
case QUERY_NODE_FUNCTION:
|
||||
return nodeArrayWalker(((SFunctionNode*)pNode)->pParameterList, walker, pContext);
|
||||
return nodesWalkNodeList(((SFunctionNode*)pNode)->pParameterList, walker, pContext);
|
||||
case QUERY_NODE_REAL_TABLE:
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
return true; // todo
|
||||
case QUERY_NODE_JOIN_TABLE: {
|
||||
SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode;
|
||||
if (!nodeTreeWalker(pJoinTableNode->pLeft, walker, pContext)) {
|
||||
if (!nodesWalkNode(pJoinTableNode->pLeft, walker, pContext)) {
|
||||
return false;
|
||||
}
|
||||
if (!nodeTreeWalker(pJoinTableNode->pRight, walker, pContext)) {
|
||||
if (!nodesWalkNode(pJoinTableNode->pRight, walker, pContext)) {
|
||||
return false;
|
||||
}
|
||||
return nodeTreeWalker(pJoinTableNode->pOnCond, walker, pContext);
|
||||
return nodesWalkNode(pJoinTableNode->pOnCond, walker, pContext);
|
||||
}
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
return nodeArrayWalker(((SGroupingSetNode*)pNode)->pParameterList, walker, pContext);
|
||||
return nodesWalkNodeList(((SGroupingSetNode*)pNode)->pParameterList, walker, pContext);
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
return nodeTreeWalker(((SOrderByExprNode*)pNode)->pExpr, walker, pContext);
|
||||
return nodesWalkNode(((SOrderByExprNode*)pNode)->pExpr, walker, pContext);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -78,6 +79,6 @@ bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool stmtWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
|
||||
bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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 "nodes.h"
|
||||
#include "nodesShowStmts.h"
|
||||
|
||||
bool nodesIsTimeorderQuery(const SNode* pQuery) {
|
||||
|
||||
}
|
||||
|
||||
bool nodesIsTimelineQuery(const SNode* pQuery) {
|
||||
|
||||
}
|
||||
|
||||
static SNode* makeNode(ENodeType type, size_t size) {
|
||||
SNode* p = calloc(1, size);
|
||||
setNodeType(p, type);
|
||||
return p;
|
||||
}
|
||||
|
||||
SNode* nodesMakeNode(ENodeType type) {
|
||||
switch (type) {
|
||||
case QUERY_NODE_COLUMN:
|
||||
return makeNode(type, sizeof(SColumnNode));
|
||||
case QUERY_NODE_VALUE:
|
||||
return makeNode(type, sizeof(SValueNode));
|
||||
case QUERY_NODE_OPERATOR:
|
||||
return makeNode(type, sizeof(SOperatorNode));
|
||||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
return makeNode(type, sizeof(SLogicConditionNode));
|
||||
case QUERY_NODE_IS_NULL_CONDITION:
|
||||
return makeNode(type, sizeof(SIsNullCondNode));
|
||||
case QUERY_NODE_FUNCTION:
|
||||
return makeNode(type, sizeof(SFunctionNode));
|
||||
case QUERY_NODE_REAL_TABLE:
|
||||
return makeNode(type, sizeof(SRealTableNode));
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
return makeNode(type, sizeof(STempTableNode));
|
||||
case QUERY_NODE_JOIN_TABLE:
|
||||
return makeNode(type, sizeof(SJoinTableNode));
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
return makeNode(type, sizeof(SGroupingSetNode));
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
return makeNode(type, sizeof(SOrderByExprNode));
|
||||
case QUERY_NODE_LIMIT:
|
||||
return makeNode(type, sizeof(SLimitNode));
|
||||
case QUERY_NODE_STATE_WINDOW:
|
||||
return makeNode(type, sizeof(SStateWindowNode));
|
||||
case QUERY_NODE_SESSION_WINDOW:
|
||||
return makeNode(type, sizeof(SSessionWindowNode));
|
||||
case QUERY_NODE_INTERVAL_WINDOW:
|
||||
return makeNode(type, sizeof(SIntervalWindowNode));
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return makeNode(type, sizeof(SSetOperator));
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
return makeNode(type, sizeof(SSelectStmt));
|
||||
case QUERY_NODE_SHOW_STMT:
|
||||
return makeNode(type, sizeof(SShowStmt));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nodesDestroyNode(SNode* pNode) {
|
||||
|
||||
}
|
||||
|
||||
void nodesDestroyNodeList(SNodeList* pList) {
|
||||
|
||||
}
|
Loading…
Reference in New Issue