提交 d5107df7 编写于 作者: X Xiaoyu Wang

TD-13120 SELECT statement syntax definition

上级 d7e304f0
......@@ -207,52 +207,36 @@
#define TK_INTO 189
#define TK_VALUES 190
#define NEW_TK_OR 1
#define NEW_TK_AND 2
#define NEW_TK_NOT 3
#define NEW_TK_EQ 4
#define NEW_TK_NE 5
#define NEW_TK_ISNULL 6
#define NEW_TK_NOTNULL 7
#define NEW_TK_IS 8
#define NEW_TK_LIKE 9
#define NEW_TK_MATCH 10
#define NEW_TK_NMATCH 11
#define NEW_TK_GLOB 12
#define NEW_TK_BETWEEN 13
#define NEW_TK_IN 14
#define NEW_TK_GT 15
#define NEW_TK_GE 16
#define NEW_TK_LT 17
#define NEW_TK_LE 18
#define NEW_TK_BITAND 19
#define NEW_TK_BITOR 20
#define NEW_TK_LSHIFT 21
#define NEW_TK_RSHIFT 22
#define NEW_TK_NK_PLUS 23
#define NEW_TK_NK_MINUS 24
#define NEW_TK_DIVIDE 25
#define NEW_TK_TIMES 26
#define NEW_TK_NK_STAR 27
#define NEW_TK_NK_SLASH 28
#define NEW_TK_REM 29
#define NEW_TK_CONCAT 30
#define NEW_TK_UMINUS 31
#define NEW_TK_UPLUS 32
#define NEW_TK_BITNOT 33
#define NEW_TK_SHOW 34
#define NEW_TK_DATABASES 35
#define NEW_TK_NK_ID 36
#define NEW_TK_NK_LP 37
#define NEW_TK_NK_RP 38
#define NEW_TK_NK_COMMA 39
#define NEW_TK_NK_LITERAL 40
#define NEW_TK_NK_DOT 41
#define NEW_TK_SELECT 42
#define NEW_TK_DISTINCT 43
#define NEW_TK_ALL 44
#define NEW_TK_AS 45
#define NEW_TK_FROM 46
#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
......
......@@ -20,7 +20,6 @@
extern "C" {
#endif
#include "tarray.h"
#include "tdef.h"
typedef enum ENodeType {
......@@ -35,6 +34,7 @@ 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,
......@@ -53,6 +53,7 @@ typedef struct SNode {
} SNode;
#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type)
#define setNodeType(nodeptr, type) (((SNode*)(nodeptr))->type = (type))
typedef struct SListCell {
SNode* pNode;
......@@ -64,8 +65,15 @@ typedef struct SNodeList {
SListCell* pHeader;
} SNodeList;
#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 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;
......@@ -142,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 {
......@@ -155,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 {
......@@ -165,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;
......@@ -179,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;
......@@ -193,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 {
......@@ -214,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
......@@ -240,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 {
......@@ -264,8 +274,8 @@ typedef struct SSetOperator {
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
bool nodesWalkArray(SArray* pArray, FQueryNodeWalker walker, void* pContext);
bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext);
bool nodesWalkNodeList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext);
bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext);
......
......@@ -17,23 +17,37 @@
#include "nodesShowStmts.h"
#include "parser.h"
typedef void* (*FMalloc)(size_t);
typedef void (*FFree)(void*);
#ifndef _TD_AST_CREATE_FUNCS_H_
#define _TD_AST_CREATE_FUNCS_H_
typedef struct SAstCreaterContext {
#ifdef __cplusplus
extern "C" {
#endif
typedef struct SAstCreateContext {
SParseContext* pQueryCxt;
bool notSupport;
bool valid;
SNode* pRootNode;
FMalloc mallocFunc;
FFree freeFunc;
} SAstCreaterContext;
SNodeList* addNodeToList(SAstCreaterContext* pCxt, SNodeList* pList, SNode* pNode);
SNode* createColumnNode(SAstCreaterContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pColumnName);
SNodeList* createNodeList(SAstCreaterContext* pCxt, SNode* pNode);
SNode* createOrderByExprNode(SAstCreaterContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder);
SNode* createSelectStmt(SAstCreaterContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable);
SNode* createSetOperator(SAstCreaterContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight);
SNode* createShowStmt(SAstCreaterContext* pCxt, EShowStmtType type);
SNode* setProjectionAlias(SAstCreaterContext* pCxt, SNode* pNode, SToken* pAlias);
} SAstCreateContext;
int32_t createAstCreater(const SParseContext* pQueryCxt, SAstCreateContext* pCxt);
int32_t destroyAstCreater(SAstCreateContext* pCxt);
bool checkTableName(const SToken* pTableName);
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode);
SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableName, const SToken* pColumnName);
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_*/
/*
* 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 SQuery {
SNode* pRoot;
} SQuery;
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
#ifdef __cplusplus
}
#endif
#endif /*_TD_AST_CREATER_H_*/
......@@ -4,11 +4,11 @@
%name NewParse
%token_prefix NEW_TK_
%token_type { SToken* }
%token_type { SToken }
%default_type { SNode* }
%default_destructor { nodesDestroyNode($$); }
%extra_argument { SAstCreaterContext* pCxt }
%extra_argument { SAstCreateContext* pCxt }
%include {
#include <stdio.h>
......@@ -21,19 +21,21 @@
#include "ttoken.h"
#include "ttokendef.h"
#include "astCreateFuncs.h"
#define PARSER_TRACE printf("rule = %s\n", yyRuleName[yyruleno])
}
%syntax_error {
if(TOKEN->z) {
if(TOKEN.z) {
char msg[] = "syntax error near \"%s\"";
int32_t sqlLen = strlen(&TOKEN->z[0]);
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);
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]);
sprintf(pCxt->pQueryCxt->pMsg, msg, &TOKEN.z[0]);
}
} else {
sprintf(pCxt->pQueryCxt->pMsg, "Incomplete SQL statement");
......@@ -56,9 +58,9 @@
//%left CONCAT.
//%right UMINUS UPLUS BITNOT.
cmd ::= SHOW DATABASES. { createShowStmt(pCxt, SHOW_TYPE_DATABASE); }
cmd ::= SHOW DATABASES. { PARSER_TRACE; createShowStmt(pCxt, SHOW_TYPE_DATABASE); }
cmd ::= query_expression(A). { pCxt->pRootNode = A; }
cmd ::= query_expression(A). { PARSER_TRACE; pCxt->pRootNode = A; }
//////////////////////// value_function /////////////////////////////////
value_function ::= NK_ID NK_LP value_expression NK_RP.
......@@ -74,9 +76,8 @@ nonparenthesized_value_expression_primary ::= column_reference.
literal ::= NK_LITERAL.
column_reference(A) ::= NK_ID(B). { A = createColumnNode(pCxt, NULL, NULL, B); }
column_reference(A) ::= NK_ID(B) NK_DOT NK_ID(C). { A = createColumnNode(pCxt, NULL, B, C); }
column_reference(A) ::= NK_ID(B) NK_DOT NK_ID(C) NK_DOT NK_ID(D). { A = createColumnNode(pCxt, B, C, D); }
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.
......@@ -95,43 +96,64 @@ 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). { A = createSelectStmt(pCxt, B, C, D); }
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) ::= . { A = false; }
set_quantifier_opt(A) ::= DISTINCT. { A = true; }
set_quantifier_opt(A) ::= ALL. { A = false; }
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. { A = NULL; }
select_list(A) ::= select_sublist(B). { A = B; }
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). { A = createNodeList(pCxt, B); }
select_sublist(A) ::= select_sublist(B) NK_COMMA select_item(C). { A = addNodeToList(pCxt, B, C); }
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). { A = B; }
select_item(A) ::= value_expression(B) AS NK_ID(C). { A = setProjectionAlias(pCxt, B, C); }
select_item(A) ::= NK_ID(B) NK_DOT NK_STAR(C). { A = createColumnNode(pCxt, NULL, B, C); }
select_item(A) ::= NK_ID(B) NK_DOT NK_ID(C) NK_DOT NK_STAR(D). { A = createColumnNode(pCxt, B, C, D); }
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 ::= FROM table_reference_list.
from_clause(A) ::= FROM table_reference_list(B). { PARSER_TRACE; A = B; }
table_reference_list ::= table_reference.
table_reference_list ::= table_reference_list NK_COMMA table_reference.
//%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 ::= NK_ID.
//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 limit_clause_opt slimit_clause_opt. { A = B; }
query_expression(A) ::= with_clause_opt query_expression_body(B) order_by_clause_opt limit_clause_opt slimit_clause_opt. { PARSER_TRACE; A = B; }
with_clause_opt ::= . {}
with_clause_opt ::= WITH with_list. { pCxt->notSupport = true; pCxt->valid = false; }
with_clause_opt ::= WITH RECURSIVE with_list. { pCxt->notSupport = true; pCxt->valid = false; }
with_clause_opt ::= WITH with_list. { PARSER_TRACE; pCxt->notSupport = true; pCxt->valid = false; }
with_clause_opt ::= WITH RECURSIVE with_list. { PARSER_TRACE; pCxt->notSupport = true; pCxt->valid = false; }
with_list ::= with_list_element. {}
with_list ::= with_list NK_COMMA with_list_element. {}
......@@ -140,16 +162,16 @@ with_list_element ::= NK_ID AS table_subquery. {}
table_subquery ::= . {}
query_expression_body(A) ::= query_primary(B). { A = B; }
query_expression_body(A) ::= query_expression_body(B) UNION ALL query_expression_body(C). { A = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, B, C); }
query_expression_body(A) ::= query_primary(B). { PARSER_TRACE; A = B; }
query_expression_body(A) ::= query_expression_body(B) UNION ALL query_expression_body(C). { PARSER_TRACE; A = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, B, C); }
query_primary(A) ::= query_specification(B). { A = B; }
query_primary(A) ::= NK_LP query_expression_body(B) order_by_clause_opt limit_clause_opt slimit_clause_opt NK_RP. { A = B;}
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) ::= . { A = NULL; }
order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { A = B; }
order_by_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; }
order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { PARSER_TRACE; A = B; }
limit_clause_opt ::= .
......@@ -158,19 +180,19 @@ slimit_clause_opt ::= .
//////////////////////// sort_specification_list /////////////////////////////////
%type sort_specification_list { SNodeList* }
%destructor sort_specification_list { nodesDestroyNodeList($$); }
sort_specification_list(A) ::= sort_specification(B). { A = createNodeList(pCxt, B); }
sort_specification_list(A) ::= sort_specification_list(B) NK_COMMA sort_specification(C). { A = addNodeToList(pCxt, B, C); }
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). { A = createOrderByExprNode(pCxt, B, C, D); }
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) ::= . { A = ORDER_ASC; }
ordering_specification_opt(A) ::= ASC. { A = ORDER_ASC; }
ordering_specification_opt(A) ::= DESC. { A = ORDER_DESC; }
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) ::= . { A = NULL_ORDER_DEFAULT; }
null_ordering_opt(A) ::= NULLS FIRST. { A = NULL_ORDER_FIRST; }
null_ordering_opt(A) ::= NULLS LAST. { A = NULL_ORDER_LAST; }
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; }
......@@ -15,57 +15,162 @@
#include "ttoken.h"
#include "astCreateFuncs.h"
#include "astCreater.h"
typedef void* (*FMalloc)(size_t);
typedef void (*FFree)(void*);
extern void* NewParseAlloc(FMalloc);
extern void NewParse(void*, int, SToken*, void*);
extern void NewParse(void*, int, SToken, void*);
extern void NewParseFree(void*, FFree);
SNodeList* addNodeToList(SAstCreaterContext* pCxt, SNodeList* pList, SNode* pNode) {
static void* acquireRaii(SAstCreateContext* pCxt, void* p) {
if (NULL == p) {
return NULL;
}
return p;
}
static void* releaseRaii(SAstCreateContext* pCxt, void* p) {
if (NULL == p) {
return NULL;
}
return p;
}
SNode* createColumnNode(SAstCreaterContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pColumnName) {
int32_t createAstCreater(const SParseContext* pQueryCxt, SAstCreateContext* pCxt) {
}
SNodeList* createNodeList(SAstCreaterContext* pCxt, SNode* pNode) {
int32_t destroyAstCreater(SAstCreateContext* pCxt) {
}
SNode* createOrderByExprNode(SAstCreaterContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder) {
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* createSelectStmt(SAstCreaterContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable) {
SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableName, const SToken* pColumnName) {
}
SNode* createSetOperator(SAstCreaterContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) {
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) {
}
SNode* createShowStmt(SAstCreaterContext* pCxt, EShowStmtType type) {
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder) {
}
SNode* setProjectionAlias(SAstCreaterContext* pCxt, SNode* pNode, SToken* pAlias) {
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* doParse(SParseContext* pParseCxt) {
SAstCreaterContext cxt = { .pQueryCxt = pParseCxt, .valid = true, .pRootNode = NULL, .mallocFunc = malloc, .freeFunc = free};
void *pParser = NewParseAlloc(cxt.mallocFunc);
SNode* createShowStmt(SAstCreateContext* pCxt, EShowStmtType type) {
}
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) {
}
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);
NewParse(pParser, 0, t0, &cxt);
goto abort_parse;
}
t0.n = tGetToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type);
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) {
......@@ -74,13 +179,14 @@ SNode* doParse(SParseContext* pParseCxt) {
break;
}
case TK_SEMI: {
NewParse(pParser, 0, &t0, &cxt);
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;
}
......@@ -88,11 +194,12 @@ SNode* doParse(SParseContext* pParseCxt) {
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);
NewParse(pParser, t0.type, t0, &cxt);
if (!cxt.valid) {
goto abort_parse;
}
......@@ -100,6 +207,7 @@ SNode* doParse(SParseContext* pParseCxt) {
}
abort_parse:
NewParseFree(pParser, cxt.freeFunc);
return cxt.pRootNode;
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
)
/*
* 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 "astCreater.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);
}
......@@ -16,7 +16,28 @@
#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) {
......
......@@ -36,13 +36,13 @@
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 (!nodesEqualNode((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,7 +97,7 @@ 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;
}
......@@ -132,6 +132,7 @@ bool nodesEqualNode(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,14 +17,14 @@
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
bool nodesWalkArray(SArray* pArray, FQueryNodeWalker walker, void* pContext) {
size_t size = taosArrayGetSize(pArray);
for (size_t i = 0; i < size; ++i) {
if (!nodesWalkNode((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 nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
......@@ -39,6 +39,7 @@ bool nodesWalkNode(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: {
......@@ -49,11 +50,11 @@ bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
return nodesWalkNode(pOpNode->pRight, walker, pContext);
}
case QUERY_NODE_LOGIC_CONDITION:
return nodesWalkArray(((SLogicConditionNode*)pNode)->pParameterList, walker, pContext);
return nodesWalkNodeList(((SLogicConditionNode*)pNode)->pParameterList, walker, pContext);
case QUERY_NODE_IS_NULL_CONDITION:
return nodesWalkNode(((SIsNullCondNode*)pNode)->pExpr, walker, pContext);
case QUERY_NODE_FUNCTION:
return nodesWalkArray(((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
......@@ -68,7 +69,7 @@ bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
return nodesWalkNode(pJoinTableNode->pOnCond, walker, pContext);
}
case QUERY_NODE_GROUPING_SET:
return nodesWalkArray(((SGroupingSetNode*)pNode)->pParameterList, walker, pContext);
return nodesWalkNodeList(((SGroupingSetNode*)pNode)->pParameterList, walker, pContext);
case QUERY_NODE_ORDER_BY_EXPR:
return nodesWalkNode(((SOrderByExprNode*)pNode)->pExpr, walker, pContext);
default:
......
......@@ -14,6 +14,7 @@
*/
#include "nodes.h"
#include "nodesShowStmts.h"
bool nodesIsTimeorderQuery(const SNode* pQuery) {
......@@ -23,8 +24,54 @@ bool nodesIsTimelineQuery(const SNode* pQuery) {
}
SNode* nodesMakeNode(ENodeType type) {
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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册