未验证 提交 09071e70 编写于 作者: X xiao-yu-wang 提交者: GitHub

Merge pull request #10031 from taosdata/feature/3.0_wxy

TD-13197 SELECT statement syntax definition
...@@ -86,6 +86,7 @@ tests/comparisonTest/opentsdb/opentsdbtest/.settings/ ...@@ -86,6 +86,7 @@ tests/comparisonTest/opentsdb/opentsdbtest/.settings/
tests/examples/JDBC/JDBCDemo/.classpath tests/examples/JDBC/JDBCDemo/.classpath
tests/examples/JDBC/JDBCDemo/.project tests/examples/JDBC/JDBCDemo/.project
tests/examples/JDBC/JDBCDemo/.settings/ tests/examples/JDBC/JDBCDemo/.settings/
source/libs/parser/inc/new_sql.*
# Emacs # Emacs
# -*- mode: gitignore; -*- # -*- mode: gitignore; -*-
...@@ -101,4 +102,4 @@ TAGS ...@@ -101,4 +102,4 @@ TAGS
contrib/* contrib/*
!contrib/CMakeLists.txt !contrib/CMakeLists.txt
!contrib/test !contrib/test
\ No newline at end of file
...@@ -207,6 +207,36 @@ ...@@ -207,6 +207,36 @@
#define TK_INTO 189 #define TK_INTO 189
#define TK_VALUES 190 #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_SPACE 300
#define TK_COMMENT 301 #define TK_COMMENT 301
......
...@@ -35,7 +35,7 @@ typedef struct SQueryNode { ...@@ -35,7 +35,7 @@ typedef struct SQueryNode {
int16_t type; int16_t type;
} SQueryNode; } SQueryNode;
#define nodeType(nodeptr) (((const SQueryNode*)(nodeptr))->type) #define queryNodeType(nodeptr) (((const SQueryNode*)(nodeptr))->type)
typedef struct SField { typedef struct SField {
char name[TSDB_COL_NAME_LEN]; char name[TSDB_COL_NAME_LEN];
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
extern "C" { extern "C" {
#endif #endif
#include "tarray.h"
#include "tdef.h" #include "tdef.h"
typedef enum ENodeType { typedef enum ENodeType {
...@@ -35,12 +34,14 @@ typedef enum ENodeType { ...@@ -35,12 +34,14 @@ typedef enum ENodeType {
QUERY_NODE_JOIN_TABLE, QUERY_NODE_JOIN_TABLE,
QUERY_NODE_GROUPING_SET, QUERY_NODE_GROUPING_SET,
QUERY_NODE_ORDER_BY_EXPR, QUERY_NODE_ORDER_BY_EXPR,
QUERY_NODE_LIMIT,
QUERY_NODE_STATE_WINDOW, QUERY_NODE_STATE_WINDOW,
QUERY_NODE_SESSION_WINDOW, QUERY_NODE_SESSION_WINDOW,
QUERY_NODE_INTERVAL_WINDOW, QUERY_NODE_INTERVAL_WINDOW,
QUERY_NODE_SET_OPERATOR, QUERY_NODE_SET_OPERATOR,
QUERY_NODE_SELECT_STMT QUERY_NODE_SELECT_STMT,
QUERY_NODE_SHOW_STMT
} ENodeType; } ENodeType;
/** /**
...@@ -52,6 +53,27 @@ typedef struct SNode { ...@@ -52,6 +53,27 @@ typedef struct SNode {
} SNode; } SNode;
#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type) #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 { typedef struct SDataType {
uint8_t type; uint8_t type;
...@@ -128,7 +150,7 @@ typedef enum ELogicConditionType { ...@@ -128,7 +150,7 @@ typedef enum ELogicConditionType {
typedef struct SLogicConditionNode { typedef struct SLogicConditionNode {
ENodeType type; // QUERY_NODE_LOGIC_CONDITION ENodeType type; // QUERY_NODE_LOGIC_CONDITION
ELogicConditionType condType; ELogicConditionType condType;
SArray* pParameterList; SNodeList* pParameterList;
} SLogicConditionNode; } SLogicConditionNode;
typedef struct SIsNullCondNode { typedef struct SIsNullCondNode {
...@@ -141,7 +163,7 @@ typedef struct SFunctionNode { ...@@ -141,7 +163,7 @@ typedef struct SFunctionNode {
SExprNode type; // QUERY_NODE_FUNCTION SExprNode type; // QUERY_NODE_FUNCTION
char functionName[TSDB_FUNC_NAME_LEN]; char functionName[TSDB_FUNC_NAME_LEN];
int32_t funcId; int32_t funcId;
SArray* pParameterList; // SNode SNodeList* pParameterList; // SNode
} SFunctionNode; } SFunctionNode;
typedef struct STableNode { typedef struct STableNode {
...@@ -151,12 +173,12 @@ typedef struct STableNode { ...@@ -151,12 +173,12 @@ typedef struct STableNode {
} STableNode; } STableNode;
typedef struct SRealTableNode { typedef struct SRealTableNode {
STableNode type; // QUERY_NODE_REAL_TABLE STableNode table; // QUERY_NODE_REAL_TABLE
char dbName[TSDB_DB_NAME_LEN]; char dbName[TSDB_DB_NAME_LEN];
} SRealTableNode; } SRealTableNode;
typedef struct STempTableNode { typedef struct STempTableNode {
STableNode type; // QUERY_NODE_TEMP_TABLE STableNode table; // QUERY_NODE_TEMP_TABLE
SNode* pSubquery; SNode* pSubquery;
} STempTableNode; } STempTableNode;
...@@ -165,7 +187,7 @@ typedef enum EJoinType { ...@@ -165,7 +187,7 @@ typedef enum EJoinType {
} EJoinType; } EJoinType;
typedef struct SJoinTableNode { typedef struct SJoinTableNode {
STableNode type; // QUERY_NODE_JOIN_TABLE STableNode table; // QUERY_NODE_JOIN_TABLE
EJoinType joinType; EJoinType joinType;
SNode* pLeft; SNode* pLeft;
SNode* pRight; SNode* pRight;
...@@ -179,7 +201,7 @@ typedef enum EGroupingSetType { ...@@ -179,7 +201,7 @@ typedef enum EGroupingSetType {
typedef struct SGroupingSetNode { typedef struct SGroupingSetNode {
ENodeType type; // QUERY_NODE_GROUPING_SET ENodeType type; // QUERY_NODE_GROUPING_SET
EGroupingSetType groupingSetType; EGroupingSetType groupingSetType;
SArray* pParameterList; SNodeList* pParameterList;
} SGroupingSetNode; } SGroupingSetNode;
typedef enum EOrder { typedef enum EOrder {
...@@ -188,7 +210,8 @@ typedef enum EOrder { ...@@ -188,7 +210,8 @@ typedef enum EOrder {
} EOrder; } EOrder;
typedef enum ENullOrder { typedef enum ENullOrder {
NULL_ORDER_FIRST = 1, NULL_ORDER_DEFAULT = 1,
NULL_ORDER_FIRST,
NULL_ORDER_LAST NULL_ORDER_LAST
} ENullOrder; } ENullOrder;
...@@ -199,10 +222,11 @@ typedef struct SOrderByExprNode { ...@@ -199,10 +222,11 @@ typedef struct SOrderByExprNode {
ENullOrder nullOrder; ENullOrder nullOrder;
} SOrderByExprNode; } SOrderByExprNode;
typedef struct SLimitInfo { typedef struct SLimitNode {
ENodeType type; // QUERY_NODE_LIMIT
uint64_t limit; uint64_t limit;
uint64_t offset; uint64_t offset;
} SLimitInfo; } SLimitNode;
typedef struct SStateWindowNode { typedef struct SStateWindowNode {
ENodeType type; // QUERY_NODE_STATE_WINDOW ENodeType type; // QUERY_NODE_STATE_WINDOW
...@@ -225,15 +249,16 @@ typedef struct SIntervalWindowNode { ...@@ -225,15 +249,16 @@ typedef struct SIntervalWindowNode {
typedef struct SSelectStmt { typedef struct SSelectStmt {
ENodeType type; // QUERY_NODE_SELECT_STMT ENodeType type; // QUERY_NODE_SELECT_STMT
bool isDistinct; bool isDistinct;
SArray* pProjectionList; // SNode bool isStar;
SNodeList* pProjectionList; // SNode
SNode* pFromTable; SNode* pFromTable;
SNode* pWhereCond; SNode* pWhereCond;
SArray* pPartitionByList; // SNode SNodeList* pPartitionByList; // SNode
SNode* pWindowClause; SNode* pWindowClause;
SArray* pGroupByList; // SGroupingSetNode SNodeList* pGroupByList; // SGroupingSetNode
SArray* pOrderByList; // SOrderByExprNode SNodeList* pOrderByList; // SOrderByExprNode
SLimitInfo limit; SLimitNode limit;
SLimitInfo slimit; SLimitNode slimit;
} SSelectStmt; } SSelectStmt;
typedef enum ESetOperatorType { typedef enum ESetOperatorType {
...@@ -249,20 +274,24 @@ typedef struct SSetOperator { ...@@ -249,20 +274,24 @@ typedef struct SSetOperator {
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext); typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
bool nodeArrayWalker(SArray* pArray, FQueryNodeWalker walker, void* pContext); bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext);
bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext); bool nodesWalkNodeList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext);
bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext);
bool stmtWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext); bool nodesEqualNode(const SNode* a, const SNode* b);
bool nodeEqual(const SNode* a, const SNode* b); void nodesCloneNode(const SNode* pNode);
void cloneNode(const SNode* pNode); int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
int32_t nodeToString(const SNode* pNode, char** pStr, int32_t* pLen); bool nodesIsTimeorderQuery(const SNode* pQuery);
int32_t stringToNode(const char* pStr, SNode** pNode); bool nodesIsTimelineQuery(const SNode* pQuery);
bool isTimeorderQuery(const SNode* pQuery); SNode* nodesMakeNode(ENodeType type);
bool isTimelineQuery(const SNode* pQuery); void nodesDestroyNode(SNode* pNode);
void nodesDestroyNodeList(SNodeList* pList);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
/*
* 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( ...@@ -8,7 +8,7 @@ target_include_directories(
target_link_libraries( target_link_libraries(
parser parser
PRIVATE os util catalog function transport qcom PRIVATE os util nodes catalog function transport qcom
) )
if(${BUILD_TEST}) if(${BUILD_TEST})
......
/*
* 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_*/
/*
* 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_*/
//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 @@ ...@@ -14,11 +14,23 @@
*/ */
#include "nodes.h" #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 stringToNode(const char* pStr, SNode** pNode) { int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
#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/>.
*/
#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) {
}
/*
* 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 @@ ...@@ -13,12 +13,6 @@
* 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 "nodes.h" // int32_t doTranslate() {
bool isTimeorderQuery(const SNode* pQuery) { // }
}
bool isTimelineQuery(const SNode* pQuery) {
}
/*
** 2000-05-29
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** Driver template for the LEMON parser generator.
**
** The "lemon" program processes an LALR(1) input grammar file, then uses
** this template to construct a parser. The "lemon" program inserts text
** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
** interstitial "-" characters) contained in this template is changed into
** the value of the %name directive from the grammar. Otherwise, the content
** of this template is copied straight through into the generate parser
** source file.
**
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
#include <stdio.h>
#include <assert.h>
/************ Begin %include sections from the grammar ************************/
#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])
/**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols
** in a format understandable to "makeheaders". This section is blank unless
** "lemon" is run with the "-m" command-line option.
***************** Begin makeheaders token definitions *************************/
/**************** End makeheaders token definitions ***************************/
/* The next sections is a series of control #defines.
** various aspects of the generated parser.
** YYCODETYPE is the data type used to store the integer codes
** that represent terminal and non-terminal symbols.
** "unsigned char" is used if there are fewer than
** 256 symbols. Larger types otherwise.
** YYNOCODE is a number of type YYCODETYPE that is not used for
** any terminal or nonterminal symbol.
** YYFALLBACK If defined, this indicates that one or more tokens
** (also known as: "terminal symbols") have fall-back
** values which should be used if the original symbol
** would not parse. This permits keywords to sometimes
** be used as identifiers, for example.
** YYACTIONTYPE is the data type used for "action codes" - numbers
** that indicate what to do in response to the next
** token.
** NewParseTOKENTYPE is the data type used for minor type for terminal
** symbols. Background: A "minor type" is a semantic
** value associated with a terminal or non-terminal
** symbols. For example, for an "ID" terminal symbol,
** the minor type might be the name of the identifier.
** Each non-terminal can have a different minor type.
** Terminal symbols all have the same minor type, though.
** This macros defines the minor type for terminal
** symbols.
** YYMINORTYPE is the data type used for all minor types.
** This is typically a union of many types, one of
** which is NewParseTOKENTYPE. The entry in the union
** for terminal symbols is called "yy0".
** YYSTACKDEPTH is the maximum depth of the parser's stack. If
** zero the stack is dynamically sized using realloc()
** NewParseARG_SDECL A static variable declaration for the %extra_argument
** NewParseARG_PDECL A parameter declaration for the %extra_argument
** NewParseARG_PARAM Code to pass %extra_argument as a subroutine parameter
** NewParseARG_STORE Code to store %extra_argument into yypParser
** NewParseARG_FETCH Code to extract %extra_argument from yypParser
** NewParseCTX_* As NewParseARG_ except for %extra_context
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YYNTOKEN Number of terminal symbols
** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
** YY_ERROR_ACTION The yy_action[] code for syntax error
** YY_ACCEPT_ACTION The yy_action[] code for accept
** YY_NO_ACTION The yy_action[] code for no-op
** YY_MIN_REDUCE Minimum value for reduce actions
** YY_MAX_REDUCE Maximum value for reduce actions
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned char
#define YYNOCODE 71
#define YYACTIONTYPE unsigned char
#define NewParseTOKENTYPE SToken
typedef union {
int yyinit;
NewParseTOKENTYPE yy0;
bool yy9;
SNodeList* yy30;
SToken yy67;
ENullOrder yy68;
EOrder yy108;
SNode* yy130;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
#define NewParseARG_SDECL SAstCreateContext* pCxt ;
#define NewParseARG_PDECL , SAstCreateContext* pCxt
#define NewParseARG_PARAM ,pCxt
#define NewParseARG_FETCH SAstCreateContext* pCxt =yypParser->pCxt ;
#define NewParseARG_STORE yypParser->pCxt =pCxt ;
#define NewParseCTX_SDECL
#define NewParseCTX_PDECL
#define NewParseCTX_PARAM
#define NewParseCTX_FETCH
#define NewParseCTX_STORE
#define YYNSTATE 63
#define YYNRULE 68
#define YYNTOKEN 35
#define YY_MAX_SHIFT 62
#define YY_MIN_SHIFTREDUCE 114
#define YY_MAX_SHIFTREDUCE 181
#define YY_ERROR_ACTION 182
#define YY_ACCEPT_ACTION 183
#define YY_NO_ACTION 184
#define YY_MIN_REDUCE 185
#define YY_MAX_REDUCE 252
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
**
** Applications can choose to define yytestcase() in the %include section
** to a macro that can assist in verifying code coverage. For production
** code the yytestcase() macro should be turned off. But it is useful
** for testing.
*/
#ifndef yytestcase
# define yytestcase(X)
#endif
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.
**
** Suppose the action integer is N. Then the action is determined as
** follows
**
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
** token onto the stack and goto state N.
**
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
**
** N == YY_ERROR_ACTION A syntax error has occurred.
**
** N == YY_ACCEPT_ACTION The parser accepts its input.
**
** N == YY_NO_ACTION No such action. Denotes unused
** slots in the yy_action[] table.
**
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE
**
** The action table is constructed as a single large table named yy_action[].
** Given state S and lookahead X, the action is computed as either:
**
** (A) N = yy_action[ yy_shift_ofst[S] + X ]
** (B) N = yy_default[S]
**
** The (A) formula is preferred. The B formula is used instead if
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X.
**
** The formulas above are for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array.
**
** The following are the tables generated in this section:
**
** yy_action[] A single table containing all actions.
** yy_lookahead[] A table containing the lookahead for each entry in
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
#define YY_ACTTAB_COUNT (229)
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 30, 50, 30, 30, 30, 30, 55, 50, 30, 30,
/* 10 */ 10, 9, 29, 62, 51, 195, 30, 19, 30, 30,
/* 20 */ 30, 30, 57, 19, 30, 30, 30, 19, 30, 30,
/* 30 */ 30, 30, 57, 19, 30, 30, 30, 50, 30, 30,
/* 40 */ 30, 30, 55, 50, 30, 30, 39, 222, 155, 156,
/* 50 */ 23, 196, 12, 11, 10, 9, 25, 223, 30, 58,
/* 60 */ 30, 30, 30, 30, 57, 58, 30, 30, 30, 59,
/* 70 */ 30, 30, 30, 30, 57, 59, 30, 30, 30, 37,
/* 80 */ 30, 30, 30, 30, 57, 37, 30, 30, 204, 38,
/* 90 */ 5, 183, 60, 166, 158, 159, 121, 53, 200, 201,
/* 100 */ 202, 203, 54, 203, 203, 203, 246, 18, 246, 246,
/* 110 */ 246, 246, 57, 120, 246, 246, 245, 17, 245, 245,
/* 120 */ 245, 245, 57, 46, 245, 245, 35, 27, 35, 35,
/* 130 */ 35, 35, 57, 31, 35, 35, 36, 47, 36, 36,
/* 140 */ 36, 36, 57, 128, 36, 36, 242, 117, 242, 242,
/* 150 */ 242, 242, 57, 42, 241, 242, 241, 241, 241, 241,
/* 160 */ 57, 52, 212, 241, 14, 13, 122, 1, 212, 212,
/* 170 */ 38, 5, 14, 13, 166, 40, 224, 20, 38, 5,
/* 180 */ 15, 210, 166, 211, 21, 22, 17, 210, 210, 43,
/* 190 */ 160, 6, 7, 45, 41, 26, 207, 48, 24, 208,
/* 200 */ 136, 44, 205, 8, 189, 3, 142, 2, 16, 127,
/* 210 */ 147, 146, 32, 150, 49, 149, 4, 33, 180, 206,
/* 220 */ 28, 117, 34, 186, 56, 162, 161, 185, 61,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
/* 10 */ 8, 9, 49, 10, 51, 52, 37, 38, 39, 40,
/* 20 */ 41, 42, 43, 44, 45, 46, 37, 38, 39, 40,
/* 30 */ 41, 42, 43, 44, 45, 46, 37, 38, 39, 40,
/* 40 */ 41, 42, 43, 44, 45, 46, 67, 68, 30, 31,
/* 50 */ 69, 52, 6, 7, 8, 9, 63, 68, 37, 38,
/* 60 */ 39, 40, 41, 42, 43, 44, 45, 46, 37, 38,
/* 70 */ 39, 40, 41, 42, 43, 44, 45, 46, 37, 38,
/* 80 */ 39, 40, 41, 42, 43, 44, 45, 46, 43, 12,
/* 90 */ 13, 35, 36, 16, 33, 34, 2, 12, 53, 54,
/* 100 */ 55, 56, 57, 58, 59, 60, 37, 22, 39, 40,
/* 110 */ 41, 42, 43, 19, 45, 46, 37, 61, 39, 40,
/* 120 */ 41, 42, 43, 15, 45, 46, 37, 63, 39, 40,
/* 130 */ 41, 42, 43, 32, 45, 46, 37, 29, 39, 40,
/* 140 */ 41, 42, 43, 8, 45, 46, 37, 12, 39, 40,
/* 150 */ 41, 42, 43, 1, 37, 46, 39, 40, 41, 42,
/* 160 */ 43, 36, 47, 46, 6, 7, 8, 48, 47, 47,
/* 170 */ 12, 13, 6, 7, 16, 23, 70, 62, 12, 13,
/* 180 */ 13, 66, 16, 62, 62, 18, 61, 66, 66, 15,
/* 190 */ 14, 15, 13, 25, 64, 64, 17, 28, 65, 65,
/* 200 */ 12, 27, 43, 21, 50, 15, 14, 24, 2, 12,
/* 210 */ 26, 26, 26, 26, 20, 26, 15, 26, 14, 17,
/* 220 */ 17, 12, 17, 0, 17, 14, 14, 0, 11, 71,
/* 230 */ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
/* 240 */ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
/* 250 */ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
/* 260 */ 71, 71, 71, 71,
};
#define YY_SHIFT_COUNT (62)
#define YY_SHIFT_MIN (0)
#define YY_SHIFT_MAX (227)
static const unsigned short int yy_shift_ofst[] = {
/* 0 */ 3, 158, 166, 166, 166, 166, 166, 166, 85, 166,
/* 10 */ 166, 166, 166, 77, 77, 167, 167, 167, 229, 18,
/* 20 */ 152, 152, 94, 101, 168, 169, 169, 168, 188, 182,
/* 30 */ 46, 61, 174, 108, 135, 2, 2, 176, 179, 190,
/* 40 */ 183, 192, 206, 184, 185, 186, 187, 189, 191, 197,
/* 50 */ 194, 201, 204, 202, 203, 205, 209, 207, 211, 212,
/* 60 */ 223, 227, 217,
};
#define YY_REDUCE_COUNT (29)
#define YY_REDUCE_MIN (-37)
#define YY_REDUCE_MAX (159)
static const short yy_reduce_ofst[] = {
/* 0 */ 56, -37, -21, -11, -1, 21, 31, 41, 45, 69,
/* 10 */ 79, 89, 99, 109, 117, 115, 121, 122, 125, -19,
/* 20 */ -7, 64, 119, 106, 130, 133, 134, 131, 159, 154,
};
static const YYACTIONTYPE yy_default[] = {
/* 0 */ 209, 182, 182, 182, 182, 182, 182, 182, 182, 182,
/* 10 */ 182, 182, 182, 182, 182, 182, 182, 182, 209, 225,
/* 20 */ 214, 214, 190, 228, 216, 219, 219, 216, 182, 182,
/* 30 */ 239, 182, 182, 182, 182, 244, 243, 182, 187, 215,
/* 40 */ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
/* 50 */ 197, 194, 182, 207, 182, 182, 182, 182, 182, 182,
/* 60 */ 182, 182, 182,
};
/********** End of lemon-generated parsing tables *****************************/
/* The next table maps tokens (terminal symbols) into fallback tokens.
** If a construct like the following:
**
** %fallback ID X Y Z.
**
** appears in the grammar, then ID becomes a fallback token for X, Y,
** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
** but it does not parse, the type of the token is changed to ID and
** the parse is retried before an error is thrown.
**
** This feature can be used, for example, to cause some keywords in a language
** to revert to identifiers if they keyword does not apply in the context where
** it appears.
*/
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
** parser's stack. Information stored includes:
**
** + The state number for the parser at this level of the stack.
**
** + The value of the token stored at this level of the stack.
** (In other words, the "major" token.)
**
** + The semantic value stored at this level of the stack. This is
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
**
** After the "shift" half of a SHIFTREDUCE action, the stateno field
** actually contains the reduce action for the second half of the
** SHIFTREDUCE.
*/
struct yyStackEntry {
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
YYCODETYPE major; /* The major token value. This is the code
** number for the token at this stack level */
YYMINORTYPE minor; /* The user-supplied minor token value. This
** is the value of the token */
};
typedef struct yyStackEntry yyStackEntry;
/* The state of the parser is completely contained in an instance of
** the following structure */
struct yyParser {
yyStackEntry *yytos; /* Pointer to top element of the stack */
#ifdef YYTRACKMAXSTACKDEPTH
int yyhwm; /* High-water mark of the stack */
#endif
#ifndef YYNOERRORRECOVERY
int yyerrcnt; /* Shifts left before out of the error */
#endif
NewParseARG_SDECL /* A place to hold %extra_argument */
NewParseCTX_SDECL /* A place to hold %extra_context */
#if YYSTACKDEPTH<=0
int yystksz; /* Current side of the stack */
yyStackEntry *yystack; /* The parser's stack */
yyStackEntry yystk0; /* First stack entry */
#else
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
yyStackEntry *yystackEnd; /* Last entry in the stack */
#endif
};
typedef struct yyParser yyParser;
#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
#ifndef NDEBUG
/*
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message. Tracing is turned off
** by making either argument NULL
**
** Inputs:
** <ul>
** <li> A FILE* to which trace output should be written.
** If NULL, then tracing is turned off.
** <li> A prefix string written at the beginning of every
** line of trace output. If NULL, then tracing is
** turned off.
** </ul>
**
** Outputs:
** None.
*/
void NewParseTrace(FILE *TraceFILE, char *zTracePrompt){
yyTraceFILE = TraceFILE;
yyTracePrompt = zTracePrompt;
if( yyTraceFILE==0 ) yyTracePrompt = 0;
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}
#endif /* NDEBUG */
#if defined(YYCOVERAGE) || !defined(NDEBUG)
/* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */
static const char *const yyTokenName[] = {
/* 0 */ "$",
/* 1 */ "UNION",
/* 2 */ "ALL",
/* 3 */ "MINUS",
/* 4 */ "EXCEPT",
/* 5 */ "INTERSECT",
/* 6 */ "NK_PLUS",
/* 7 */ "NK_MINUS",
/* 8 */ "NK_STAR",
/* 9 */ "NK_SLASH",
/* 10 */ "SHOW",
/* 11 */ "DATABASES",
/* 12 */ "NK_ID",
/* 13 */ "NK_LP",
/* 14 */ "NK_RP",
/* 15 */ "NK_COMMA",
/* 16 */ "NK_LITERAL",
/* 17 */ "NK_DOT",
/* 18 */ "SELECT",
/* 19 */ "DISTINCT",
/* 20 */ "AS",
/* 21 */ "FROM",
/* 22 */ "NK_LR",
/* 23 */ "ORDER",
/* 24 */ "BY",
/* 25 */ "SLIMIT",
/* 26 */ "NK_INTEGER",
/* 27 */ "SOFFSET",
/* 28 */ "LIMIT",
/* 29 */ "OFFSET",
/* 30 */ "ASC",
/* 31 */ "DESC",
/* 32 */ "NULLS",
/* 33 */ "FIRST",
/* 34 */ "LAST",
/* 35 */ "cmd",
/* 36 */ "query_expression",
/* 37 */ "value_function",
/* 38 */ "value_expression",
/* 39 */ "value_expression_primary",
/* 40 */ "nonparenthesized_value_expression_primary",
/* 41 */ "literal",
/* 42 */ "column_reference",
/* 43 */ "table_name",
/* 44 */ "common_value_expression",
/* 45 */ "numeric_value_expression",
/* 46 */ "numeric_primary",
/* 47 */ "query_specification",
/* 48 */ "set_quantifier_opt",
/* 49 */ "select_list",
/* 50 */ "from_clause",
/* 51 */ "select_sublist",
/* 52 */ "select_item",
/* 53 */ "table_reference_list",
/* 54 */ "table_reference",
/* 55 */ "table_factor",
/* 56 */ "table_primary",
/* 57 */ "db_name",
/* 58 */ "derived_table",
/* 59 */ "table_subquery",
/* 60 */ "subquery",
/* 61 */ "with_clause_opt",
/* 62 */ "query_expression_body",
/* 63 */ "order_by_clause_opt",
/* 64 */ "slimit_clause_opt",
/* 65 */ "limit_clause_opt",
/* 66 */ "query_primary",
/* 67 */ "sort_specification_list",
/* 68 */ "sort_specification",
/* 69 */ "ordering_specification_opt",
/* 70 */ "null_ordering_opt",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {
/* 0 */ "cmd ::= SHOW DATABASES",
/* 1 */ "cmd ::= query_expression",
/* 2 */ "column_reference ::= NK_ID",
/* 3 */ "column_reference ::= table_name NK_DOT NK_ID",
/* 4 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause",
/* 5 */ "set_quantifier_opt ::=",
/* 6 */ "set_quantifier_opt ::= DISTINCT",
/* 7 */ "set_quantifier_opt ::= ALL",
/* 8 */ "select_list ::= NK_STAR",
/* 9 */ "select_list ::= select_sublist",
/* 10 */ "select_sublist ::= select_item",
/* 11 */ "select_sublist ::= select_sublist NK_COMMA select_item",
/* 12 */ "select_item ::= value_expression",
/* 13 */ "select_item ::= value_expression AS NK_ID",
/* 14 */ "select_item ::= table_name NK_DOT NK_STAR",
/* 15 */ "from_clause ::= FROM table_reference_list",
/* 16 */ "table_reference_list ::= table_reference",
/* 17 */ "table_reference ::= table_factor",
/* 18 */ "table_factor ::= table_primary",
/* 19 */ "table_primary ::= table_name",
/* 20 */ "table_primary ::= db_name NK_DOT table_name",
/* 21 */ "db_name ::= NK_ID",
/* 22 */ "table_name ::= NK_ID",
/* 23 */ "query_expression ::= with_clause_opt query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt",
/* 24 */ "with_clause_opt ::=",
/* 25 */ "query_expression_body ::= query_primary",
/* 26 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body",
/* 27 */ "query_primary ::= query_specification",
/* 28 */ "query_primary ::= NK_LP query_expression_body order_by_clause_opt limit_clause_opt slimit_clause_opt NK_RP",
/* 29 */ "order_by_clause_opt ::=",
/* 30 */ "order_by_clause_opt ::= ORDER BY sort_specification_list",
/* 31 */ "slimit_clause_opt ::=",
/* 32 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER",
/* 33 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER",
/* 34 */ "limit_clause_opt ::=",
/* 35 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER",
/* 36 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER",
/* 37 */ "sort_specification_list ::= sort_specification",
/* 38 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification",
/* 39 */ "sort_specification ::= value_expression ordering_specification_opt null_ordering_opt",
/* 40 */ "ordering_specification_opt ::=",
/* 41 */ "ordering_specification_opt ::= ASC",
/* 42 */ "ordering_specification_opt ::= DESC",
/* 43 */ "null_ordering_opt ::=",
/* 44 */ "null_ordering_opt ::= NULLS FIRST",
/* 45 */ "null_ordering_opt ::= NULLS LAST",
/* 46 */ "value_function ::= NK_ID NK_LP value_expression NK_RP",
/* 47 */ "value_function ::= NK_ID NK_LP value_expression NK_COMMA value_expression NK_RP",
/* 48 */ "value_expression_primary ::= NK_LP value_expression NK_RP",
/* 49 */ "value_expression_primary ::= nonparenthesized_value_expression_primary",
/* 50 */ "nonparenthesized_value_expression_primary ::= literal",
/* 51 */ "nonparenthesized_value_expression_primary ::= column_reference",
/* 52 */ "literal ::= NK_LITERAL",
/* 53 */ "value_expression ::= common_value_expression",
/* 54 */ "common_value_expression ::= numeric_value_expression",
/* 55 */ "numeric_value_expression ::= numeric_primary",
/* 56 */ "numeric_value_expression ::= NK_PLUS numeric_primary",
/* 57 */ "numeric_value_expression ::= NK_MINUS numeric_primary",
/* 58 */ "numeric_value_expression ::= numeric_value_expression NK_PLUS numeric_value_expression",
/* 59 */ "numeric_value_expression ::= numeric_value_expression NK_MINUS numeric_value_expression",
/* 60 */ "numeric_value_expression ::= numeric_value_expression NK_STAR numeric_value_expression",
/* 61 */ "numeric_value_expression ::= numeric_value_expression NK_SLASH numeric_value_expression",
/* 62 */ "numeric_primary ::= value_expression_primary",
/* 63 */ "numeric_primary ::= value_function",
/* 64 */ "table_primary ::= derived_table",
/* 65 */ "derived_table ::= table_subquery",
/* 66 */ "subquery ::= NK_LR query_expression NK_RP",
/* 67 */ "table_subquery ::= subquery",
};
#endif /* NDEBUG */
#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack. Return the number
** of errors. Return 0 on success.
*/
static int yyGrowStack(yyParser *p){
int newSize;
int idx;
yyStackEntry *pNew;
newSize = p->yystksz*2 + 100;
idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
if( p->yystack==&p->yystk0 ){
pNew = malloc(newSize*sizeof(pNew[0]));
if( pNew ) pNew[0] = p->yystk0;
}else{
pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
}
if( pNew ){
p->yystack = pNew;
p->yytos = &p->yystack[idx];
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
yyTracePrompt, p->yystksz, newSize);
}
#endif
p->yystksz = newSize;
}
return pNew==0;
}
#endif
/* Datatype of the argument to the memory allocated passed as the
** second argument to NewParseAlloc() below. This can be changed by
** putting an appropriate #define in the %include section of the input
** grammar.
*/
#ifndef YYMALLOCARGTYPE
# define YYMALLOCARGTYPE size_t
#endif
/* Initialize a new parser that has already been allocated.
*/
void NewParseInit(void *yypRawParser NewParseCTX_PDECL){
yyParser *yypParser = (yyParser*)yypRawParser;
NewParseCTX_STORE
#ifdef YYTRACKMAXSTACKDEPTH
yypParser->yyhwm = 0;
#endif
#if YYSTACKDEPTH<=0
yypParser->yytos = NULL;
yypParser->yystack = NULL;
yypParser->yystksz = 0;
if( yyGrowStack(yypParser) ){
yypParser->yystack = &yypParser->yystk0;
yypParser->yystksz = 1;
}
#endif
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
yypParser->yytos = yypParser->yystack;
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
#if YYSTACKDEPTH>0
yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
#endif
}
#ifndef NewParse_ENGINEALWAYSONSTACK
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser. This pointer is used in subsequent calls
** to NewParse and NewParseFree.
*/
void *NewParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) NewParseCTX_PDECL){
yyParser *yypParser;
yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
if( yypParser ){
NewParseCTX_STORE
NewParseInit(yypParser NewParseCTX_PARAM);
}
return (void*)yypParser;
}
#endif /* NewParse_ENGINEALWAYSONSTACK */
/* The following function deletes the "minor type" or semantic value
** associated with a symbol. The symbol can be either a terminal
** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
** a pointer to the value to be deleted. The code used to do the
** deletions is derived from the %destructor and/or %token_destructor
** directives of the input grammar.
*/
static void yy_destructor(
yyParser *yypParser, /* The parser */
YYCODETYPE yymajor, /* Type code for object to destroy */
YYMINORTYPE *yypminor /* The object to be destroyed */
){
NewParseARG_FETCH
NewParseCTX_FETCH
switch( yymajor ){
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
** reduce or during error processing or when a parser is
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are *not* used
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
/* Default NON-TERMINAL Destructor */
case 35: /* cmd */
case 36: /* query_expression */
case 37: /* value_function */
case 38: /* value_expression */
case 39: /* value_expression_primary */
case 40: /* nonparenthesized_value_expression_primary */
case 41: /* literal */
case 42: /* column_reference */
case 43: /* table_name */
case 44: /* common_value_expression */
case 45: /* numeric_value_expression */
case 46: /* numeric_primary */
case 47: /* query_specification */
case 50: /* from_clause */
case 52: /* select_item */
case 53: /* table_reference_list */
case 54: /* table_reference */
case 55: /* table_factor */
case 56: /* table_primary */
case 57: /* db_name */
case 58: /* derived_table */
case 59: /* table_subquery */
case 60: /* subquery */
case 61: /* with_clause_opt */
case 62: /* query_expression_body */
case 64: /* slimit_clause_opt */
case 65: /* limit_clause_opt */
case 66: /* query_primary */
case 68: /* sort_specification */
{
nodesDestroyNode((yypminor->yy130));
}
break;
case 48: /* set_quantifier_opt */
{
}
break;
case 49: /* select_list */
case 51: /* select_sublist */
case 63: /* order_by_clause_opt */
case 67: /* sort_specification_list */
{
nodesDestroyNodeList((yypminor->yy30));
}
break;
case 69: /* ordering_specification_opt */
{
}
break;
case 70: /* null_ordering_opt */
{
}
break;
/********* End destructor definitions *****************************************/
default: break; /* If no destructor action specified: do nothing */
}
}
/*
** Pop the parser's stack once.
**
** If there is a destructor routine associated with the token which
** is popped from the stack, then call it.
*/
static void yy_pop_parser_stack(yyParser *pParser){
yyStackEntry *yytos;
assert( pParser->yytos!=0 );
assert( pParser->yytos > pParser->yystack );
yytos = pParser->yytos--;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sPopping %s\n",
yyTracePrompt,
yyTokenName[yytos->major]);
}
#endif
yy_destructor(pParser, yytos->major, &yytos->minor);
}
/*
** Clear all secondary memory allocations from the parser
*/
void NewParseFinalize(void *p){
yyParser *pParser = (yyParser*)p;
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif
}
#ifndef NewParse_ENGINEALWAYSONSTACK
/*
** Deallocate and destroy a parser. Destructors are called for
** all stack elements before shutting the parser down.
**
** If the YYPARSEFREENEVERNULL macro exists (for example because it
** is defined in a %include section of the input grammar) then it is
** assumed that the input pointer is never NULL.
*/
void NewParseFree(
void *p, /* The parser to be deleted */
void (*freeProc)(void*) /* Function used to reclaim memory */
){
#ifndef YYPARSEFREENEVERNULL
if( p==0 ) return;
#endif
NewParseFinalize(p);
(*freeProc)(p);
}
#endif /* NewParse_ENGINEALWAYSONSTACK */
/*
** Return the peak depth of the stack for a parser.
*/
#ifdef YYTRACKMAXSTACKDEPTH
int NewParseStackPeak(void *p){
yyParser *pParser = (yyParser*)p;
return pParser->yyhwm;
}
#endif
/* This array of booleans keeps track of the parser statement
** coverage. The element yycoverage[X][Y] is set when the parser
** is in state X and has a lookahead token Y. In a well-tested
** systems, every element of this matrix should end up being set.
*/
#if defined(YYCOVERAGE)
static unsigned char yycoverage[YYNSTATE][YYNTOKEN];
#endif
/*
** Write into out a description of every state/lookahead combination that
**
** (1) has not been used by the parser, and
** (2) is not a syntax error.
**
** Return the number of missed state/lookahead combinations.
*/
#if defined(YYCOVERAGE)
int NewParseCoverage(FILE *out){
int stateno, iLookAhead, i;
int nMissed = 0;
for(stateno=0; stateno<YYNSTATE; stateno++){
i = yy_shift_ofst[stateno];
for(iLookAhead=0; iLookAhead<YYNTOKEN; iLookAhead++){
if( yy_lookahead[i+iLookAhead]!=iLookAhead ) continue;
if( yycoverage[stateno][iLookAhead]==0 ) nMissed++;
if( out ){
fprintf(out,"State %d lookahead %s %s\n", stateno,
yyTokenName[iLookAhead],
yycoverage[stateno][iLookAhead] ? "ok" : "missed");
}
}
}
return nMissed;
}
#endif
/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
*/
static YYACTIONTYPE yy_find_shift_action(
YYCODETYPE iLookAhead, /* The look-ahead token */
YYACTIONTYPE stateno /* Current state number */
){
int i;
if( stateno>YY_MAX_SHIFT ) return stateno;
assert( stateno <= YY_SHIFT_COUNT );
#if defined(YYCOVERAGE)
yycoverage[stateno][iLookAhead] = 1;
#endif
do{
i = yy_shift_ofst[stateno];
assert( i>=0 );
/* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */
assert( iLookAhead!=YYNOCODE );
assert( iLookAhead < YYNTOKEN );
i += iLookAhead;
if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
}
#endif
assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
iLookAhead = iFallback;
continue;
}
#endif
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
yy_lookahead[j]==YYWILDCARD && iLookAhead>0
){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead],
yyTokenName[YYWILDCARD]);
}
#endif /* NDEBUG */
return yy_action[j];
}
}
#endif /* YYWILDCARD */
return yy_default[stateno];
}else{
return yy_action[i];
}
}while(1);
}
/*
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
*/
static YYACTIONTYPE yy_find_reduce_action(
YYACTIONTYPE stateno, /* Current state number */
YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
#ifdef YYERRORSYMBOL
if( stateno>YY_REDUCE_COUNT ){
return yy_default[stateno];
}
#else
assert( stateno<=YY_REDUCE_COUNT );
#endif
i = yy_reduce_ofst[stateno];
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
#ifdef YYERRORSYMBOL
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}
#else
assert( i>=0 && i<YY_ACTTAB_COUNT );
assert( yy_lookahead[i]==iLookAhead );
#endif
return yy_action[i];
}
/*
** The following routine is called if the stack overflows.
*/
static void yyStackOverflow(yyParser *yypParser){
NewParseARG_FETCH
NewParseCTX_FETCH
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
}
#endif
while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
/******** Begin %stack_overflow code ******************************************/
/******** End %stack_overflow code ********************************************/
NewParseARG_STORE /* Suppress warning about unused %extra_argument var */
NewParseCTX_STORE
}
/*
** Print tracing information for a SHIFT action
*/
#ifndef NDEBUG
static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){
if( yyTraceFILE ){
if( yyNewState<YYNSTATE ){
fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n",
yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
yyNewState);
}else{
fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n",
yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
yyNewState - YY_MIN_REDUCE);
}
}
}
#else
# define yyTraceShift(X,Y,Z)
#endif
/*
** Perform a shift action.
*/
static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
YYACTIONTYPE yyNewState, /* The new state to shift in */
YYCODETYPE yyMajor, /* The major token to shift in */
NewParseTOKENTYPE yyMinor /* The minor token to shift in */
){
yyStackEntry *yytos;
yypParser->yytos++;
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yytos>yypParser->yystackEnd ){
yypParser->yytos--;
yyStackOverflow(yypParser);
return;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
if( yyGrowStack(yypParser) ){
yypParser->yytos--;
yyStackOverflow(yypParser);
return;
}
}
#endif
if( yyNewState > YY_MAX_SHIFT ){
yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
}
yytos = yypParser->yytos;
yytos->stateno = yyNewState;
yytos->major = yyMajor;
yytos->minor.yy0 = yyMinor;
yyTraceShift(yypParser, yyNewState, "Shift");
}
/* The following table contains information about every rule that
** is used during the reduce.
*/
static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
signed char nrhs; /* Negative of the number of RHS symbols in the rule */
} yyRuleInfo[] = {
{ 35, -2 }, /* (0) cmd ::= SHOW DATABASES */
{ 35, -1 }, /* (1) cmd ::= query_expression */
{ 42, -1 }, /* (2) column_reference ::= NK_ID */
{ 42, -3 }, /* (3) column_reference ::= table_name NK_DOT NK_ID */
{ 47, -4 }, /* (4) query_specification ::= SELECT set_quantifier_opt select_list from_clause */
{ 48, 0 }, /* (5) set_quantifier_opt ::= */
{ 48, -1 }, /* (6) set_quantifier_opt ::= DISTINCT */
{ 48, -1 }, /* (7) set_quantifier_opt ::= ALL */
{ 49, -1 }, /* (8) select_list ::= NK_STAR */
{ 49, -1 }, /* (9) select_list ::= select_sublist */
{ 51, -1 }, /* (10) select_sublist ::= select_item */
{ 51, -3 }, /* (11) select_sublist ::= select_sublist NK_COMMA select_item */
{ 52, -1 }, /* (12) select_item ::= value_expression */
{ 52, -3 }, /* (13) select_item ::= value_expression AS NK_ID */
{ 52, -3 }, /* (14) select_item ::= table_name NK_DOT NK_STAR */
{ 50, -2 }, /* (15) from_clause ::= FROM table_reference_list */
{ 53, -1 }, /* (16) table_reference_list ::= table_reference */
{ 54, -1 }, /* (17) table_reference ::= table_factor */
{ 55, -1 }, /* (18) table_factor ::= table_primary */
{ 56, -1 }, /* (19) table_primary ::= table_name */
{ 56, -3 }, /* (20) table_primary ::= db_name NK_DOT table_name */
{ 57, -1 }, /* (21) db_name ::= NK_ID */
{ 43, -1 }, /* (22) table_name ::= NK_ID */
{ 36, -5 }, /* (23) query_expression ::= with_clause_opt query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */
{ 61, 0 }, /* (24) with_clause_opt ::= */
{ 62, -1 }, /* (25) query_expression_body ::= query_primary */
{ 62, -4 }, /* (26) query_expression_body ::= query_expression_body UNION ALL query_expression_body */
{ 66, -1 }, /* (27) query_primary ::= query_specification */
{ 66, -6 }, /* (28) query_primary ::= NK_LP query_expression_body order_by_clause_opt limit_clause_opt slimit_clause_opt NK_RP */
{ 63, 0 }, /* (29) order_by_clause_opt ::= */
{ 63, -3 }, /* (30) order_by_clause_opt ::= ORDER BY sort_specification_list */
{ 64, 0 }, /* (31) slimit_clause_opt ::= */
{ 64, -4 }, /* (32) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */
{ 64, -4 }, /* (33) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */
{ 65, 0 }, /* (34) limit_clause_opt ::= */
{ 65, -4 }, /* (35) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */
{ 65, -4 }, /* (36) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */
{ 67, -1 }, /* (37) sort_specification_list ::= sort_specification */
{ 67, -3 }, /* (38) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */
{ 68, -3 }, /* (39) sort_specification ::= value_expression ordering_specification_opt null_ordering_opt */
{ 69, 0 }, /* (40) ordering_specification_opt ::= */
{ 69, -1 }, /* (41) ordering_specification_opt ::= ASC */
{ 69, -1 }, /* (42) ordering_specification_opt ::= DESC */
{ 70, 0 }, /* (43) null_ordering_opt ::= */
{ 70, -2 }, /* (44) null_ordering_opt ::= NULLS FIRST */
{ 70, -2 }, /* (45) null_ordering_opt ::= NULLS LAST */
{ 37, -4 }, /* (46) value_function ::= NK_ID NK_LP value_expression NK_RP */
{ 37, -6 }, /* (47) value_function ::= NK_ID NK_LP value_expression NK_COMMA value_expression NK_RP */
{ 39, -3 }, /* (48) value_expression_primary ::= NK_LP value_expression NK_RP */
{ 39, -1 }, /* (49) value_expression_primary ::= nonparenthesized_value_expression_primary */
{ 40, -1 }, /* (50) nonparenthesized_value_expression_primary ::= literal */
{ 40, -1 }, /* (51) nonparenthesized_value_expression_primary ::= column_reference */
{ 41, -1 }, /* (52) literal ::= NK_LITERAL */
{ 38, -1 }, /* (53) value_expression ::= common_value_expression */
{ 44, -1 }, /* (54) common_value_expression ::= numeric_value_expression */
{ 45, -1 }, /* (55) numeric_value_expression ::= numeric_primary */
{ 45, -2 }, /* (56) numeric_value_expression ::= NK_PLUS numeric_primary */
{ 45, -2 }, /* (57) numeric_value_expression ::= NK_MINUS numeric_primary */
{ 45, -3 }, /* (58) numeric_value_expression ::= numeric_value_expression NK_PLUS numeric_value_expression */
{ 45, -3 }, /* (59) numeric_value_expression ::= numeric_value_expression NK_MINUS numeric_value_expression */
{ 45, -3 }, /* (60) numeric_value_expression ::= numeric_value_expression NK_STAR numeric_value_expression */
{ 45, -3 }, /* (61) numeric_value_expression ::= numeric_value_expression NK_SLASH numeric_value_expression */
{ 46, -1 }, /* (62) numeric_primary ::= value_expression_primary */
{ 46, -1 }, /* (63) numeric_primary ::= value_function */
{ 56, -1 }, /* (64) table_primary ::= derived_table */
{ 58, -1 }, /* (65) derived_table ::= table_subquery */
{ 60, -3 }, /* (66) subquery ::= NK_LR query_expression NK_RP */
{ 59, -1 }, /* (67) table_subquery ::= subquery */
};
static void yy_accept(yyParser*); /* Forward Declaration */
/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
**
** The yyLookahead and yyLookaheadToken parameters provide reduce actions
** access to the lookahead token (if any). The yyLookahead will be YYNOCODE
** if the lookahead token has already been consumed. As this procedure is
** only called from one place, optimizing compilers will in-line it, which
** means that the extra parameters have no performance impact.
*/
static YYACTIONTYPE yy_reduce(
yyParser *yypParser, /* The parser */
unsigned int yyruleno, /* Number of the rule by which to reduce */
int yyLookahead, /* Lookahead token, or YYNOCODE if none */
NewParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */
NewParseCTX_PDECL /* %extra_context */
){
int yygoto; /* The next state */
YYACTIONTYPE yyact; /* The next action */
yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */
NewParseARG_FETCH
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
#ifndef NDEBUG
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
}else{
fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
}
}
#endif /* NDEBUG */
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfo[yyruleno].nrhs==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yytos>=yypParser->yystackEnd ){
yyStackOverflow(yypParser);
/* The call to yyStackOverflow() above pops the stack until it is
** empty, causing the main parser loop to exit. So the return value
** is never used and does not matter. */
return 0;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
if( yyGrowStack(yypParser) ){
yyStackOverflow(yypParser);
/* The call to yyStackOverflow() above pops the stack until it is
** empty, causing the main parser loop to exit. So the return value
** is never used and does not matter. */
return 0;
}
yymsp = yypParser->yytos;
}
#endif
}
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
** follows:
** case 0:
** #line <lineno> <grammarfile>
** { ... } // User supplied code
** #line <lineno> <thisfile>
** break;
*/
/********** Begin reduce actions **********************************************/
YYMINORTYPE yylhsminor;
case 0: /* cmd ::= SHOW DATABASES */
{ PARSER_TRACE; createShowStmt(pCxt, SHOW_TYPE_DATABASE); }
break;
case 1: /* cmd ::= query_expression */
{ PARSER_TRACE; pCxt->pRootNode = yymsp[0].minor.yy130; }
break;
case 2: /* column_reference ::= NK_ID */
{ PARSER_TRACE; yylhsminor.yy130 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0); }
yymsp[0].minor.yy130 = yylhsminor.yy130;
break;
case 3: /* column_reference ::= table_name NK_DOT NK_ID */
case 14: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==14);
{ PARSER_TRACE; yylhsminor.yy130 = createColumnNode(pCxt, &yymsp[-2].minor.yy67, &yymsp[0].minor.yy0); }
yymsp[-2].minor.yy130 = yylhsminor.yy130;
break;
case 4: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause */
{ PARSER_TRACE; yymsp[-3].minor.yy130 = createSelectStmt(pCxt, yymsp[-2].minor.yy9, yymsp[-1].minor.yy30, yymsp[0].minor.yy130); }
break;
case 5: /* set_quantifier_opt ::= */
{ PARSER_TRACE; yymsp[1].minor.yy9 = false; }
break;
case 6: /* set_quantifier_opt ::= DISTINCT */
{ PARSER_TRACE; yymsp[0].minor.yy9 = true; }
break;
case 7: /* set_quantifier_opt ::= ALL */
{ PARSER_TRACE; yymsp[0].minor.yy9 = false; }
break;
case 8: /* select_list ::= NK_STAR */
{ PARSER_TRACE; yymsp[0].minor.yy30 = NULL; }
break;
case 9: /* select_list ::= select_sublist */
{ PARSER_TRACE; yylhsminor.yy30 = yymsp[0].minor.yy30; }
yymsp[0].minor.yy30 = yylhsminor.yy30;
break;
case 10: /* select_sublist ::= select_item */
case 37: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==37);
{ PARSER_TRACE; yylhsminor.yy30 = createNodeList(pCxt, yymsp[0].minor.yy130); }
yymsp[0].minor.yy30 = yylhsminor.yy30;
break;
case 11: /* select_sublist ::= select_sublist NK_COMMA select_item */
case 38: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==38);
{ PARSER_TRACE; yylhsminor.yy30 = addNodeToList(pCxt, yymsp[-2].minor.yy30, yymsp[0].minor.yy130); }
yymsp[-2].minor.yy30 = yylhsminor.yy30;
break;
case 12: /* select_item ::= value_expression */
case 16: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==16);
case 17: /* table_reference ::= table_factor */ yytestcase(yyruleno==17);
case 18: /* table_factor ::= table_primary */ yytestcase(yyruleno==18);
case 25: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==25);
case 27: /* query_primary ::= query_specification */ yytestcase(yyruleno==27);
{ PARSER_TRACE; yylhsminor.yy130 = yymsp[0].minor.yy130; }
yymsp[0].minor.yy130 = yylhsminor.yy130;
break;
case 13: /* select_item ::= value_expression AS NK_ID */
{ PARSER_TRACE; yylhsminor.yy130 = setProjectionAlias(pCxt, yymsp[-2].minor.yy130, &yymsp[0].minor.yy0); }
yymsp[-2].minor.yy130 = yylhsminor.yy130;
break;
case 15: /* from_clause ::= FROM table_reference_list */
{ PARSER_TRACE; yymsp[-1].minor.yy130 = yymsp[0].minor.yy130; }
break;
case 19: /* table_primary ::= table_name */
{ PARSER_TRACE; yylhsminor.yy130 = createRealTableNode(pCxt, NULL, &yymsp[0].minor.yy67); }
yymsp[0].minor.yy130 = yylhsminor.yy130;
break;
case 20: /* table_primary ::= db_name NK_DOT table_name */
{ PARSER_TRACE; yylhsminor.yy130 = createRealTableNode(pCxt, &yymsp[-2].minor.yy67, &yymsp[0].minor.yy67); }
yymsp[-2].minor.yy130 = yylhsminor.yy130;
break;
case 21: /* db_name ::= NK_ID */
case 22: /* table_name ::= NK_ID */ yytestcase(yyruleno==22);
{ PARSER_TRACE; yylhsminor.yy67 = yymsp[0].minor.yy0; }
yymsp[0].minor.yy67 = yylhsminor.yy67;
break;
case 23: /* query_expression ::= with_clause_opt query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */
{ yy_destructor(yypParser,61,&yymsp[-4].minor);
{
PARSER_TRACE;
addOrderByList(pCxt, yymsp[-3].minor.yy130, yymsp[-2].minor.yy30);
addSlimit(pCxt, yymsp[-3].minor.yy130, yymsp[-1].minor.yy130);
addLimit(pCxt, yymsp[-3].minor.yy130, yymsp[0].minor.yy130);
yymsp[-4].minor.yy130 = yymsp[-3].minor.yy130;
}
}
break;
case 24: /* with_clause_opt ::= */
{}
break;
case 26: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */
{ PARSER_TRACE; yylhsminor.yy130 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy130, yymsp[0].minor.yy130); }
yymsp[-3].minor.yy130 = yylhsminor.yy130;
break;
case 28: /* query_primary ::= NK_LP query_expression_body order_by_clause_opt limit_clause_opt slimit_clause_opt NK_RP */
{ PARSER_TRACE; yymsp[-5].minor.yy130 = yymsp[-4].minor.yy130;}
yy_destructor(yypParser,63,&yymsp[-3].minor);
yy_destructor(yypParser,65,&yymsp[-2].minor);
yy_destructor(yypParser,64,&yymsp[-1].minor);
break;
case 29: /* order_by_clause_opt ::= */
{ PARSER_TRACE; yymsp[1].minor.yy30 = NULL; }
break;
case 30: /* order_by_clause_opt ::= ORDER BY sort_specification_list */
{ PARSER_TRACE; yymsp[-2].minor.yy30 = yymsp[0].minor.yy30; }
break;
case 31: /* slimit_clause_opt ::= */
case 34: /* limit_clause_opt ::= */ yytestcase(yyruleno==34);
{ yymsp[1].minor.yy130 = NULL; }
break;
case 32: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */
case 35: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==35);
{ yymsp[-3].minor.yy130 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); }
break;
case 33: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */
case 36: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==36);
{ yymsp[-3].minor.yy130 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); }
break;
case 39: /* sort_specification ::= value_expression ordering_specification_opt null_ordering_opt */
{ PARSER_TRACE; yylhsminor.yy130 = createOrderByExprNode(pCxt, yymsp[-2].minor.yy130, yymsp[-1].minor.yy108, yymsp[0].minor.yy68); }
yymsp[-2].minor.yy130 = yylhsminor.yy130;
break;
case 40: /* ordering_specification_opt ::= */
{ PARSER_TRACE; yymsp[1].minor.yy108 = ORDER_ASC; }
break;
case 41: /* ordering_specification_opt ::= ASC */
{ PARSER_TRACE; yymsp[0].minor.yy108 = ORDER_ASC; }
break;
case 42: /* ordering_specification_opt ::= DESC */
{ PARSER_TRACE; yymsp[0].minor.yy108 = ORDER_DESC; }
break;
case 43: /* null_ordering_opt ::= */
{ PARSER_TRACE; yymsp[1].minor.yy68 = NULL_ORDER_DEFAULT; }
break;
case 44: /* null_ordering_opt ::= NULLS FIRST */
{ PARSER_TRACE; yymsp[-1].minor.yy68 = NULL_ORDER_FIRST; }
break;
case 45: /* null_ordering_opt ::= NULLS LAST */
{ PARSER_TRACE; yymsp[-1].minor.yy68 = NULL_ORDER_LAST; }
break;
case 46: /* value_function ::= NK_ID NK_LP value_expression NK_RP */
case 48: /* value_expression_primary ::= NK_LP value_expression NK_RP */ yytestcase(yyruleno==48);
{
}
yy_destructor(yypParser,38,&yymsp[-1].minor);
break;
case 47: /* value_function ::= NK_ID NK_LP value_expression NK_COMMA value_expression NK_RP */
{
}
yy_destructor(yypParser,38,&yymsp[-3].minor);
yy_destructor(yypParser,38,&yymsp[-1].minor);
break;
case 49: /* value_expression_primary ::= nonparenthesized_value_expression_primary */
{ yy_destructor(yypParser,40,&yymsp[0].minor);
{
}
}
break;
case 50: /* nonparenthesized_value_expression_primary ::= literal */
{ yy_destructor(yypParser,41,&yymsp[0].minor);
{
}
}
break;
case 51: /* nonparenthesized_value_expression_primary ::= column_reference */
{ yy_destructor(yypParser,42,&yymsp[0].minor);
{
}
}
break;
case 53: /* value_expression ::= common_value_expression */
{ yy_destructor(yypParser,44,&yymsp[0].minor);
{
}
}
break;
case 54: /* common_value_expression ::= numeric_value_expression */
{ yy_destructor(yypParser,45,&yymsp[0].minor);
{
}
}
break;
case 55: /* numeric_value_expression ::= numeric_primary */
{ yy_destructor(yypParser,46,&yymsp[0].minor);
{
}
}
break;
case 56: /* numeric_value_expression ::= NK_PLUS numeric_primary */
case 57: /* numeric_value_expression ::= NK_MINUS numeric_primary */ yytestcase(yyruleno==57);
{
}
yy_destructor(yypParser,46,&yymsp[0].minor);
break;
case 58: /* numeric_value_expression ::= numeric_value_expression NK_PLUS numeric_value_expression */
case 59: /* numeric_value_expression ::= numeric_value_expression NK_MINUS numeric_value_expression */ yytestcase(yyruleno==59);
case 60: /* numeric_value_expression ::= numeric_value_expression NK_STAR numeric_value_expression */ yytestcase(yyruleno==60);
case 61: /* numeric_value_expression ::= numeric_value_expression NK_SLASH numeric_value_expression */ yytestcase(yyruleno==61);
{ yy_destructor(yypParser,45,&yymsp[-2].minor);
{
}
yy_destructor(yypParser,45,&yymsp[0].minor);
}
break;
case 62: /* numeric_primary ::= value_expression_primary */
{ yy_destructor(yypParser,39,&yymsp[0].minor);
{
}
}
break;
case 63: /* numeric_primary ::= value_function */
{ yy_destructor(yypParser,37,&yymsp[0].minor);
{
}
}
break;
case 64: /* table_primary ::= derived_table */
{ yy_destructor(yypParser,58,&yymsp[0].minor);
{
}
}
break;
case 65: /* derived_table ::= table_subquery */
{ yy_destructor(yypParser,59,&yymsp[0].minor);
{
}
}
break;
case 66: /* subquery ::= NK_LR query_expression NK_RP */
{
}
yy_destructor(yypParser,36,&yymsp[-1].minor);
break;
case 67: /* table_subquery ::= subquery */
{ yy_destructor(yypParser,60,&yymsp[0].minor);
{
}
}
break;
default:
/* (52) literal ::= NK_LITERAL */ yytestcase(yyruleno==52);
break;
/********** End reduce actions ************************************************/
};
assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
/* There are no SHIFTREDUCE actions on nonterminals because the table
** generator has simplified them to pure REDUCE actions. */
assert( !(yyact>YY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) );
/* It is not possible for a REDUCE to be followed by an error */
assert( yyact!=YY_ERROR_ACTION );
yymsp += yysize+1;
yypParser->yytos = yymsp;
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yyTraceShift(yypParser, yyact, "... then shift");
return yyact;
}
/*
** The following code executes when the parse fails
*/
#ifndef YYNOERRORRECOVERY
static void yy_parse_failed(
yyParser *yypParser /* The parser */
){
NewParseARG_FETCH
NewParseCTX_FETCH
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
}
#endif
while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser fails */
/************ Begin %parse_failure code ***************************************/
/************ End %parse_failure code *****************************************/
NewParseARG_STORE /* Suppress warning about unused %extra_argument variable */
NewParseCTX_STORE
}
#endif /* YYNOERRORRECOVERY */
/*
** The following code executes when a syntax error first occurs.
*/
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
int yymajor, /* The major type of the error token */
NewParseTOKENTYPE yyminor /* The minor type of the error token */
){
NewParseARG_FETCH
NewParseCTX_FETCH
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
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;
/************ End %syntax_error code ******************************************/
NewParseARG_STORE /* Suppress warning about unused %extra_argument variable */
NewParseCTX_STORE
}
/*
** The following is executed when the parser accepts
*/
static void yy_accept(
yyParser *yypParser /* The parser */
){
NewParseARG_FETCH
NewParseCTX_FETCH
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
}
#endif
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
assert( yypParser->yytos==yypParser->yystack );
/* Here code is inserted which will be executed whenever the
** parser accepts */
/*********** Begin %parse_accept code *****************************************/
printf("parsing complete!\n" );
/*********** End %parse_accept code *******************************************/
NewParseARG_STORE /* Suppress warning about unused %extra_argument variable */
NewParseCTX_STORE
}
/* The main parser program.
** The first argument is a pointer to a structure obtained from
** "NewParseAlloc" which describes the current state of the parser.
** The second argument is the major token number. The third is
** the minor token. The fourth optional argument is whatever the
** user wants (and specified in the grammar) and is available for
** use by the action routines.
**
** Inputs:
** <ul>
** <li> A pointer to the parser (an opaque structure.)
** <li> The major token number.
** <li> The minor token number.
** <li> An option argument of a grammar-specified type.
** </ul>
**
** Outputs:
** None.
*/
void NewParse(
void *yyp, /* The parser */
int yymajor, /* The major token code number */
NewParseTOKENTYPE yyminor /* The value for the token */
NewParseARG_PDECL /* Optional %extra_argument parameter */
){
YYMINORTYPE yyminorunion;
YYACTIONTYPE yyact; /* The parser action. */
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
int yyendofinput; /* True if we are at the end of input */
#endif
#ifdef YYERRORSYMBOL
int yyerrorhit = 0; /* True if yymajor has invoked an error */
#endif
yyParser *yypParser = (yyParser*)yyp; /* The parser */
NewParseCTX_FETCH
NewParseARG_STORE
assert( yypParser->yytos!=0 );
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
yyendofinput = (yymajor==0);
#endif
yyact = yypParser->yytos->stateno;
#ifndef NDEBUG
if( yyTraceFILE ){
if( yyact < YY_MIN_REDUCE ){
fprintf(yyTraceFILE,"%sInput '%s' in state %d\n",
yyTracePrompt,yyTokenName[yymajor],yyact);
}else{
fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n",
yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE);
}
}
#endif
do{
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
yyminor NewParseCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt--;
#endif
break;
}else if( yyact==YY_ACCEPT_ACTION ){
yypParser->yytos--;
yy_accept(yypParser);
return;
}else{
assert( yyact == YY_ERROR_ACTION );
yyminorunion.yy0 = yyminor;
#ifdef YYERRORSYMBOL
int yymx;
#endif
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
}
#endif
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
** * Call the %syntax_error function.
**
** * Begin popping the stack until we enter a state where
** it is legal to shift the error symbol, then shift
** the error symbol.
**
** * Set the error count to three.
**
** * Begin accepting and shifting new tokens. No new error
** processing will occur until three tokens have been
** shifted successfully.
**
*/
if( yypParser->yyerrcnt<0 ){
yy_syntax_error(yypParser,yymajor,yyminor);
}
yymx = yypParser->yytos->major;
if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
yymajor = YYNOCODE;
}else{
while( yypParser->yytos >= yypParser->yystack
&& (yyact = yy_find_reduce_action(
yypParser->yytos->stateno,
YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
){
yy_pop_parser_stack(yypParser);
}
if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
}
}
yypParser->yyerrcnt = 3;
yyerrorhit = 1;
if( yymajor==YYNOCODE ) break;
yyact = yypParser->yytos->stateno;
#elif defined(YYNOERRORRECOVERY)
/* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
** do any kind of error recovery. Instead, simply invoke the syntax
** error routine and continue going as if nothing had happened.
**
** Applications can set this macro (for example inside %include) if
** they intend to abandon the parse upon the first syntax error seen.
*/
yy_syntax_error(yypParser,yymajor, yyminor);
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
break;
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
** * Report an error message, and throw away the input token.
**
** * If the input token is $, then fail the parse.
**
** As before, subsequent error messages are suppressed until
** three input tokens have been successfully shifted.
*/
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor, yyminor);
}
yypParser->yyerrcnt = 3;
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
}
break;
#endif
}
}while( yypParser->yytos>yypParser->yystack );
#ifndef NDEBUG
if( yyTraceFILE ){
yyStackEntry *i;
char cDiv = '[';
fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
cDiv = ' ';
}
fprintf(yyTraceFILE,"]\n");
}
#endif
return;
}
/*
** Return the fallback token corresponding to canonical token iToken, or
** 0 if iToken has no fallback.
*/
int NewParseFallback(int iToken){
#ifdef YYFALLBACK
if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){
return yyFallback[iToken];
}
#else
(void)iToken;
#endif
return 0;
}
...@@ -249,7 +249,7 @@ void qDestroyQuery(SQueryNode* pQueryNode) { ...@@ -249,7 +249,7 @@ void qDestroyQuery(SQueryNode* pQueryNode) {
return; return;
} }
int32_t type = nodeType(pQueryNode); int32_t type = queryNodeType(pQueryNode);
if (type == TSDB_SQL_INSERT || type == TSDB_SQL_CREATE_TABLE) { if (type == TSDB_SQL_INSERT || type == TSDB_SQL_CREATE_TABLE) {
SVnodeModifOpStmtInfo* pModifInfo = (SVnodeModifOpStmtInfo*)pQueryNode; SVnodeModifOpStmtInfo* pModifInfo = (SVnodeModifOpStmtInfo*)pQueryNode;
taosArrayDestroy(pModifInfo->pDataBlocks); taosArrayDestroy(pModifInfo->pDataBlocks);
......
/*
* 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( ...@@ -15,5 +15,5 @@ TARGET_INCLUDE_DIRECTORIES(
TARGET_LINK_LIBRARIES( TARGET_LINK_LIBRARIES(
parserTest 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 "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 ...@@ -74,7 +74,7 @@ int32_t createSelectPlan(const SQueryStmtInfo* pSelect, SQueryPlanNode** pQueryP
} }
int32_t createQueryPlan(const SQueryNode* pNode, SQueryPlanNode** pQueryPlan) { int32_t createQueryPlan(const SQueryNode* pNode, SQueryPlanNode** pQueryPlan) {
switch (nodeType(pNode)) { switch (queryNodeType(pNode)) {
case TSDB_SQL_SELECT: { case TSDB_SQL_SELECT: {
return createSelectPlan((const SQueryStmtInfo*)pNode, pQueryPlan); return createSelectPlan((const SQueryStmtInfo*)pNode, pQueryPlan);
} }
...@@ -395,7 +395,7 @@ SArray* createQueryPlanImpl(const SQueryStmtInfo* pQueryInfo) { ...@@ -395,7 +395,7 @@ SArray* createQueryPlanImpl(const SQueryStmtInfo* pQueryInfo) {
} }
static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) { static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) {
int32_t type = nodeType(pQueryNode); int32_t type = queryNodeType(pQueryNode);
if (type == QNODE_MODIFY) { if (type == QNODE_MODIFY) {
SDataPayloadInfo* pInfo = pQueryNode->pExtInfo; SDataPayloadInfo* pInfo = pQueryNode->pExtInfo;
......
...@@ -461,7 +461,7 @@ static void destroyDataSinkNode(SDataSink* pSinkNode) { ...@@ -461,7 +461,7 @@ static void destroyDataSinkNode(SDataSink* pSinkNode) {
return; return;
} }
if (nodeType(pSinkNode) == DSINK_Dispatch) { if (queryNodeType(pSinkNode) == DSINK_Dispatch) {
SDataDispatcher* pDdSink = (SDataDispatcher*)pSinkNode; SDataDispatcher* pDdSink = (SDataDispatcher*)pSinkNode;
tfree(pDdSink->sink.schema.pSchema); tfree(pDdSink->sink.schema.pSchema);
} }
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
#include "nodes.h" #include "nodes.h"
void cloneNode(const SNode* pNode) { void nodesCloneNode(const SNode* pNode) {
} }
/*
* 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 @@ ...@@ -32,17 +32,17 @@
#define COMPARE_NODE_FIELD(fldname) \ #define COMPARE_NODE_FIELD(fldname) \
do { \ do { \
if (!nodeEqual(a->fldname, b->fldname)) \ if (!nodesEqualNode(a->fldname, b->fldname)) \
return false; \ return false; \
} while (0) } while (0)
#define COMPARE_ARRAY_FIELD(fldname) \ #define COMPARE_NODE_LIST_FIELD(fldname) \
do { \ do { \
if (!nodeArrayEqual(a->fldname, b->fldname)) \ if (!nodeNodeListEqual(a->fldname, b->fldname)) \
return false; \ return false; \
} while (0) } while (0)
static bool nodeArrayEqual(const SArray* a, const SArray* b) { static bool nodeNodeListEqual(const SNodeList* a, const SNodeList* b) {
if (a == b) { if (a == b) {
return true; return true;
} }
...@@ -51,13 +51,13 @@ static bool nodeArrayEqual(const SArray* a, const SArray* b) { ...@@ -51,13 +51,13 @@ static bool nodeArrayEqual(const SArray* a, const SArray* b) {
return false; return false;
} }
if (taosArrayGetSize(a) != taosArrayGetSize(b)) { if (LIST_LENGTH(a) != LIST_LENGTH(b)) {
return false; return false;
} }
size_t size = taosArrayGetSize(a); SNode* na, *nb;
for (size_t i = 0; i < size; ++i) { FORBOTH(na, a, nb, b) {
if (!nodeEqual((SNode*)taosArrayGetP(a, i), (SNode*)taosArrayGetP(b, i))) { if (!nodesEqualNode(na, nb)) {
return false; return false;
} }
} }
...@@ -85,7 +85,7 @@ static bool operatorNodeEqual(const SOperatorNode* a, const SOperatorNode* b) { ...@@ -85,7 +85,7 @@ static bool operatorNodeEqual(const SOperatorNode* a, const SOperatorNode* b) {
static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicConditionNode* b) { static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicConditionNode* b) {
COMPARE_SCALAR_FIELD(condType); COMPARE_SCALAR_FIELD(condType);
COMPARE_ARRAY_FIELD(pParameterList); COMPARE_NODE_LIST_FIELD(pParameterList);
return true; return true;
} }
...@@ -97,11 +97,11 @@ static bool isNullConditionNodeEqual(const SIsNullCondNode* a, const SIsNullCond ...@@ -97,11 +97,11 @@ static bool isNullConditionNodeEqual(const SIsNullCondNode* a, const SIsNullCond
static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) { static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
COMPARE_SCALAR_FIELD(funcId); COMPARE_SCALAR_FIELD(funcId);
COMPARE_ARRAY_FIELD(pParameterList); COMPARE_NODE_LIST_FIELD(pParameterList);
return true; return true;
} }
bool nodeEqual(const SNode* a, const SNode* b) { bool nodesEqualNode(const SNode* a, const SNode* b) {
if (a == b) { if (a == b) {
return true; return true;
} }
...@@ -132,6 +132,7 @@ bool nodeEqual(const SNode* a, const SNode* b) { ...@@ -132,6 +132,7 @@ bool nodeEqual(const SNode* a, const SNode* b) {
case QUERY_NODE_JOIN_TABLE: case QUERY_NODE_JOIN_TABLE:
case QUERY_NODE_GROUPING_SET: case QUERY_NODE_GROUPING_SET:
case QUERY_NODE_ORDER_BY_EXPR: case QUERY_NODE_ORDER_BY_EXPR:
case QUERY_NODE_LIMIT:
return false; // todo return false; // todo
default: default:
break; break;
......
...@@ -17,17 +17,17 @@ ...@@ -17,17 +17,17 @@
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext); typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
bool nodeArrayWalker(SArray* pArray, FQueryNodeWalker walker, void* pContext) { bool nodesWalkNodeList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext) {
size_t size = taosArrayGetSize(pArray); SNode* node;
for (size_t i = 0; i < size; ++i) { FOREACH(node, pNodeList) {
if (!nodeTreeWalker((SNode*)taosArrayGetP(pArray, i), walker, pContext)) { if (!nodesWalkNode(node, walker, pContext)) {
return false; 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) { if (NULL == pNode) {
return true; return true;
} }
...@@ -39,38 +39,39 @@ bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) { ...@@ -39,38 +39,39 @@ bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
switch (nodeType(pNode)) { switch (nodeType(pNode)) {
case QUERY_NODE_COLUMN: case QUERY_NODE_COLUMN:
case QUERY_NODE_VALUE: case QUERY_NODE_VALUE:
case QUERY_NODE_LIMIT:
// these node types with no subnodes // these node types with no subnodes
return true; return true;
case QUERY_NODE_OPERATOR: { case QUERY_NODE_OPERATOR: {
SOperatorNode* pOpNode = (SOperatorNode*)pNode; SOperatorNode* pOpNode = (SOperatorNode*)pNode;
if (!nodeTreeWalker(pOpNode->pLeft, walker, pContext)) { if (!nodesWalkNode(pOpNode->pLeft, walker, pContext)) {
return false; return false;
} }
return nodeTreeWalker(pOpNode->pRight, walker, pContext); return nodesWalkNode(pOpNode->pRight, walker, pContext);
} }
case QUERY_NODE_LOGIC_CONDITION: 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: case QUERY_NODE_IS_NULL_CONDITION:
return nodeTreeWalker(((SIsNullCondNode*)pNode)->pExpr, walker, pContext); return nodesWalkNode(((SIsNullCondNode*)pNode)->pExpr, walker, pContext);
case QUERY_NODE_FUNCTION: 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_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE: case QUERY_NODE_TEMP_TABLE:
return true; // todo return true; // todo
case QUERY_NODE_JOIN_TABLE: { case QUERY_NODE_JOIN_TABLE: {
SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode; SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode;
if (!nodeTreeWalker(pJoinTableNode->pLeft, walker, pContext)) { if (!nodesWalkNode(pJoinTableNode->pLeft, walker, pContext)) {
return false; return false;
} }
if (!nodeTreeWalker(pJoinTableNode->pRight, walker, pContext)) { if (!nodesWalkNode(pJoinTableNode->pRight, walker, pContext)) {
return false; return false;
} }
return nodeTreeWalker(pJoinTableNode->pOnCond, walker, pContext); return nodesWalkNode(pJoinTableNode->pOnCond, walker, pContext);
} }
case QUERY_NODE_GROUPING_SET: 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: case QUERY_NODE_ORDER_BY_EXPR:
return nodeTreeWalker(((SOrderByExprNode*)pNode)->pExpr, walker, pContext); return nodesWalkNode(((SOrderByExprNode*)pNode)->pExpr, walker, pContext);
default: default:
break; break;
} }
...@@ -78,6 +79,6 @@ bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) { ...@@ -78,6 +79,6 @@ bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
return false; return false;
} }
bool stmtWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) { bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
} }
/*
* 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) {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册