Irony mysql解析模板
模板可以解析大部分sql,自测通过。在其原有的demo基础上修改的。Irony源码地址:https://github.com/IronyProject/Irony
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using Irony.Parsing; 6 7 namespace Irony.Samples.SQL { 8 // Loosely based on SQL89 grammar from Gold parser. Supports some extra TSQL constructs. 9 10 [Language("SQL", "89", "SQL 89 grammar")] 11 public class SqlGrammar : Grammar { 12 public SqlGrammar() : base(false) { //SQL is case insensitive 13 //Terminals 14 var comment = new CommentTerminal("comment", "/*", "*/"); 15 var lineComment = new CommentTerminal("line_comment", "--", "\n", "\r\n"); 16 NonGrammarTerminals.Add(comment); 17 NonGrammarTerminals.Add(lineComment); 18 var number = new NumberLiteral("number"); 19 var string_literal = new StringLiteral("string", "'", StringOptions.AllowsDoubledQuote); 20 var Id_simple = TerminalFactory.CreateSqlExtIdentifier(this, "id_simple"); //covers normal identifiers (abc) and quoted id's ([abc d], "abc d") 21 var comma = ToTerm(","); 22 var dot = ToTerm("."); 23 var star = ToTerm("*"); 24 var CREATE = ToTerm("CREATE"); 25 var NULL = ToTerm("NULL"); 26 var NOT = ToTerm("NOT"); 27 var UNIQUE = ToTerm("UNIQUE"); 28 var WITH = ToTerm("WITH"); 29 var TABLE = ToTerm("TABLE"); 30 var ALTER = ToTerm("ALTER"); 31 var ADD = ToTerm("ADD"); 32 var COLUMN = ToTerm("COLUMN"); 33 var DROP = ToTerm("DROP"); 34 var CONSTRAINT = ToTerm("CONSTRAINT"); 35 var INDEX = ToTerm("INDEX"); 36 var ON = ToTerm("ON"); 37 var KEY = ToTerm("KEY"); 38 var PRIMARY = ToTerm("PRIMARY"); 39 var INSERT = ToTerm("INSERT"); 40 var INTO = ToTerm("INTO"); 41 var UPDATE = ToTerm("UPDATE"); 42 var SET = ToTerm("SET"); 43 var VALUES = ToTerm("VALUES"); 44 var DELETE = ToTerm("DELETE"); 45 var SELECT = ToTerm("SELECT"); 46 var FROM = ToTerm("FROM"); 47 var AS = ToTerm("AS"); 48 var COUNT = ToTerm("COUNT"); 49 var JOIN = ToTerm("JOIN"); 50 var BY = ToTerm("BY"); 51 var @case = ToTerm("Case"); 52 var when = ToTerm("When"); 53 var then = ToTerm("then"); 54 var @if = ToTerm("if"); 55 var @else = ToTerm("else"); 56 var end = ToTerm("end"); 57 #region define 58 //Non-terminals 59 var Id = new NonTerminal("Id"); 60 var stmt = new NonTerminal("stmt"); 61 var createTableStmt = new NonTerminal("createTableStmt"); 62 var createIndexStmt = new NonTerminal("createIndexStmt"); 63 var alterStmt = new NonTerminal("alterStmt"); 64 var dropTableStmt = new NonTerminal("dropTableStmt"); 65 var dropIndexStmt = new NonTerminal("dropIndexStmt"); 66 var selectStmt = new NonTerminal("selectStmt"); 67 var insertStmt = new NonTerminal("insertStmt"); 68 var updateStmt = new NonTerminal("updateStmt"); 69 var deleteStmt = new NonTerminal("deleteStmt"); 70 var fieldDef = new NonTerminal("fieldDef"); 71 var fieldDefList = new NonTerminal("fieldDefList"); 72 var nullSpecOpt = new NonTerminal("nullSpecOpt"); 73 var typeName = new NonTerminal("typeName"); 74 var typeSpec = new NonTerminal("typeSpec"); 75 var typeParamsOpt = new NonTerminal("typeParams"); 76 var constraintDef = new NonTerminal("constraintDef"); 77 var constraintListOpt = new NonTerminal("constraintListOpt"); 78 var constraintTypeOpt = new NonTerminal("constraintTypeOpt"); 79 var idlist = new NonTerminal("idlist"); 80 var idlistPar = new NonTerminal("idlistPar"); 81 var uniqueOpt = new NonTerminal("uniqueOpt"); 82 var orderList = new NonTerminal("orderList"); 83 var orderMember = new NonTerminal("orderMember"); 84 var orderDirOpt = new NonTerminal("orderDirOpt"); 85 var withClauseOpt = new NonTerminal("withClauseOpt"); 86 var alterCmd = new NonTerminal("alterCmd"); 87 var insertData = new NonTerminal("insertData"); 88 var intoOpt = new NonTerminal("intoOpt"); 89 var assignList = new NonTerminal("assignList"); 90 var whereClauseOpt = new NonTerminal("whereClauseOpt"); 91 var assignment = new NonTerminal("assignment"); 92 var expression = new NonTerminal("expression"); 93 var exprList = new NonTerminal("exprList"); 94 var selRestrOpt = new NonTerminal("selRestrOpt"); 95 var selList = new NonTerminal("selList"); 96 var intoClauseOpt = new NonTerminal("intoClauseOpt"); 97 var fromClauseOpt = new NonTerminal("fromClauseOpt"); 98 var groupClauseOpt = new NonTerminal("groupClauseOpt"); 99 var havingClauseOpt = new NonTerminal("havingClauseOpt"); 100 var orderClauseOpt = new NonTerminal("orderClauseOpt"); 101 // 102 var selectClauseOpt = new NonTerminal("selectClauseOpt"); 103 var pageOpt = new NonTerminal("pageOpt"); 104 var sysFunc = new NonTerminal("sysFunc"); 105 var sysFuncArg = new NonTerminal("sysFuncArg"); 106 var sysFuncArgList = new NonTerminal("sysFuncArgList"); 107 var sysFuncName = new NonTerminal("sysFuncName"); 108 var casewhenClauseOpt = new NonTerminal("casewhenClauseOpt"); 109 // var sysFuncOpt = new NonTerminal("sysFuncOpt"); 110 111 var columnItemList = new NonTerminal("columnItemList"); 112 var columnItem = new NonTerminal("columnItem"); 113 var columnSource = new NonTerminal("columnSource"); 114 var asOpt = new NonTerminal("asOpt"); 115 var aliasOpt = new NonTerminal("aliasOpt"); 116 var aggregate = new NonTerminal("aggregate"); 117 var aggregateArg = new NonTerminal("aggregateArg"); 118 var aggregateName = new NonTerminal("aggregateName"); 119 var tuple = new NonTerminal("tuple"); 120 var joinChainOpt = new NonTerminal("joinChainOpt"); 121 var joinKindOpt = new NonTerminal("joinKindOpt"); 122 var term = new NonTerminal("term"); 123 var unExpr = new NonTerminal("unExpr"); 124 var unOp = new NonTerminal("unOp"); 125 var binExpr = new NonTerminal("binExpr"); 126 var binOp = new NonTerminal("binOp"); 127 var betweenExpr = new NonTerminal("betweenExpr"); 128 var inExpr = new NonTerminal("inExpr"); 129 var parSelectStmt = new NonTerminal("parSelectStmt"); 130 var notOpt = new NonTerminal("notOpt"); 131 var funCall = new NonTerminal("funCall"); 132 var stmtLine = new NonTerminal("stmtLine"); 133 var semiOpt = new NonTerminal("semiOpt"); 134 var stmtList = new NonTerminal("stmtList"); 135 var funArgs = new NonTerminal("funArgs"); 136 var inStmt = new NonTerminal("inStmt"); 137 #endregion 138 139 //BNF Rules 140 this.Root = stmtList; 141 stmtLine.Rule = stmt + semiOpt; 142 semiOpt.Rule = Empty | ";"; 143 stmtList.Rule = MakePlusRule(stmtList, stmtLine); 144 145 // 巴科斯范式(Backus-Naur Form)BnfExpression 146 //引号中的字符表示这些他们本身,quote表示引号 147 //引号外的字符表示语法。 148 //<> 尖括号中的内容表示必选项 149 //[] 方括号中的内容表示可选项 150 //{ }大括号中的内容表示可重复0到无数次的项 151 // | 竖线表示左右任选一项 152 //:= 冒号等于时被定义为的意思 153 // 例如: 154 // <pp>:=<tt>|<tt><pp> 155 156 //ID 157 Id.Rule = MakePlusRule(Id, dot, Id_simple)| MakePlusRule(Id, dot, star)|Id_simple+Id_simple|selectClauseOpt|casewhenClauseOpt; 158 159 stmt.Rule = createTableStmt | createIndexStmt | alterStmt 160 | dropTableStmt | dropIndexStmt 161 | selectStmt | insertStmt | updateStmt | deleteStmt 162 | "GO" ; 163 //Create table 164 #region createsql 165 createTableStmt.Rule = CREATE + TABLE + Id + "(" + fieldDefList + ")" + constraintListOpt; 166 fieldDefList.Rule = MakePlusRule(fieldDefList, comma, fieldDef); 167 fieldDef.Rule = Id + typeName + typeParamsOpt + nullSpecOpt; 168 nullSpecOpt.Rule = NULL | NOT + NULL | Empty; 169 typeName.Rule = ToTerm("BIT") | "DATE" | "TIME" | "TIMESTAMP" | "DECIMAL" | "REAL" | "FLOAT" | "SMALLINT" | "INTEGER" 170 /*| "INTERVAL" */| "CHARACTER" 171 // MS SQL types: 172 | "DATETIME" | "INT" | "DOUBLE" | "CHAR" | "NCHAR" | "VARCHAR" | "NVARCHAR" 173 | "IMAGE" | "TEXT" | "NTEXT"; 174 typeParamsOpt.Rule = "(" + number + ")" | "(" + number + comma + number + ")" | Empty; 175 constraintDef.Rule = CONSTRAINT + Id + constraintTypeOpt; 176 constraintListOpt.Rule = MakeStarRule(constraintListOpt, constraintDef ); 177 constraintTypeOpt.Rule = PRIMARY + KEY + idlistPar | UNIQUE + idlistPar | NOT + NULL + idlistPar 178 | "Foreign" + KEY + idlistPar + "References" + Id + idlistPar; 179 idlistPar.Rule = "(" + idlist + ")"; 180 idlist.Rule = MakePlusRule(idlist, comma, Id); 181 #endregion 182 #region othersql 183 //Create Index 184 createIndexStmt.Rule = CREATE + uniqueOpt + INDEX + Id + ON + Id + orderList + withClauseOpt; 185 uniqueOpt.Rule = Empty | UNIQUE; 186 orderList.Rule = MakePlusRule(orderList, comma, orderMember); 187 orderMember.Rule = Id + orderDirOpt; 188 orderDirOpt.Rule = Empty | "ASC" | "DESC"; 189 withClauseOpt.Rule = Empty | WITH + PRIMARY | WITH + "Disallow" + NULL | WITH + "Ignore" + NULL; 190 191 //Alter 192 alterStmt.Rule = ALTER + TABLE + Id + alterCmd; 193 alterCmd.Rule = ADD + COLUMN + fieldDefList + constraintListOpt 194 | ADD + constraintDef 195 | DROP + COLUMN + Id 196 | DROP + CONSTRAINT + Id; 197 198 //Drop stmts 199 dropTableStmt.Rule = DROP + TABLE + Id; 200 dropIndexStmt.Rule = DROP + INDEX + Id + ON + Id; 201 202 //Insert stmt 203 insertStmt.Rule = INSERT + intoOpt + Id + idlistPar + insertData; 204 insertData.Rule = selectStmt | VALUES + "(" + exprList + ")"; 205 intoOpt.Rule = Empty | INTO; //Into is optional in MSSQL 206 207 //Update stmt 208 updateStmt.Rule = UPDATE + Id + SET + assignList + whereClauseOpt; 209 assignList.Rule = MakePlusRule(assignList, comma, assignment); 210 assignment.Rule = Id + "=" + expression; 211 212 //Delete stmt 213 deleteStmt.Rule = DELETE + FROM + Id + whereClauseOpt; 214 #endregion 215 216 #region selectsql 217 //Select stmt 218 selectStmt.Rule = SELECT + selRestrOpt + selList + intoClauseOpt + fromClauseOpt + whereClauseOpt + 219 groupClauseOpt + havingClauseOpt + orderClauseOpt+pageOpt; 220 selRestrOpt.Rule = Empty | "ALL" | "DISTINCT"; 221 selList.Rule = columnItemList | "*"; 222 // comma:逗号 223 columnItemList.Rule = MakePlusRule(columnItemList, comma, columnItem); 224 // alias:别名 225 // columnItem匹配的是 xxx as xx 226 // 问题:怎样匹配 xx.*? 227 columnItem.Rule = columnSource + aliasOpt|columnItem+comma+ columnSource + aliasOpt; 228 aliasOpt.Rule = Empty | asOpt + Id|Id; 229 asOpt.Rule = Empty | AS; 230 columnSource.Rule = aggregate | Id|selectClauseOpt|sysFunc|expression; 231 // aggregate:聚合 232 aggregate.Rule = aggregateName + "(" + aggregateArg + ")" 233 | aggregateName + "(" + aggregateArg + ")"+binOp+number; 234 aggregateArg.Rule = expression | "*"|"distinct"+Id; 235 aggregateName.Rule = COUNT | "Avg" | "Min" | "Max" | "StDev" | "StDevP" | "Sum" | "Var" | "VarP"; 236 // 237 var whenthenClause = new NonTerminal("whenthenClause"); 238 var whenthenItem = new NonTerminal("whenthenItem"); 239 whenthenItem.Rule = when + expression + then + term; 240 whenthenClause.Rule = MakePlusRule(whenthenClause, whenthenItem); 241 // Empty| when + expression + then + term| whenthenClause + when + expression + then + term; 242 243 sysFunc.Rule = sysFuncName + "(" + sysFuncArgList + sysFuncArg + ")" 244 | sysFuncName + "(" + sysFuncArgList + "'%Y-%m-%d'" + ")" | sysFuncName + "(" + sysFuncArgList + ")" 245 | sysFuncName + number + term; 246 // | sysFuncName + "(" + sysFuncArg+comma+expression + ")" 247 ;// "date_format(, '%Y-%m-%d')"; 248 sysFuncArg.Rule = expression | "*"; 249 sysFuncArgList.Rule = Empty | MakePlusRule(sysFuncArgList, comma, sysFuncArg);// sysFuncArg + comma | sysFuncArgList+ sysFuncArg + comma; 250 251 sysFuncName.Rule = COUNT|"date_format" | "GROUP_CONCAT"| "CONCAT"| "ROUND" 252 |"if"| "unix_timestamp"|"date_sub"| "CURDATE"|"interval"; 253 casewhenClauseOpt.Rule = Empty | @case+ whenthenClause + @else+expression+ end 254 | @case +expression+ whenthenClause + @else + expression + end; 255 256 intoClauseOpt.Rule = Empty | INTO + Id; 257 fromClauseOpt.Rule = Empty | FROM + columnItem + joinChainOpt; 258 259 joinChainOpt.Rule = Empty | joinKindOpt + JOIN + idlist + ON + Id + "=" + Id; 260 // 添加字段 joinChainOpt 261 var someClauseOpt = new NonTerminal("someClauseOpt"); 262 someClauseOpt.Rule = expression;// Id + "=" + Id| someClauseOpt+"and"+ Id + "=" + Id | someClauseOpt + "&&" + Id + "=" + Id; 263 // 添加字段 joinChainOpt 264 joinChainOpt.Rule = Empty | joinChainOpt+joinKindOpt + JOIN + selectClauseOpt + ON + someClauseOpt | joinChainOpt+joinKindOpt + JOIN + idlist + ON + someClauseOpt; 265 266 // joinChainOpt.Rule = Empty | joinChainOpt+ joinKindOpt + JOIN + selectClauseOpt + ON + Id + "=" + Id| joinChainOpt + joinKindOpt + JOIN + idlist + ON + Id + "=" + Id; 267 joinKindOpt.Rule = Empty | "INNER" | "LEFT" | "RIGHT"| joinKindOpt+"OUTER"; 268 whereClauseOpt.Rule = Empty | "WHERE" + expression; 269 groupClauseOpt.Rule = Empty | "GROUP" + BY + idlist; 270 havingClauseOpt.Rule = Empty | "HAVING" + expression; 271 orderClauseOpt.Rule = Empty | "ORDER" + BY + orderList; 272 selectClauseOpt.Rule = "(" + selectStmt.Rule + ")"+ aliasOpt ; 273 pageOpt.Rule = Empty | "limit" + number | "limit" + number + comma + number; 274 275 #endregion 276 277 //Expression 278 exprList.Rule = MakePlusRule(exprList, comma, expression); 279 expression.Rule = term | unExpr | binExpr| betweenExpr| sysFunc; //-- BETWEEN doesn't work - yet; brings a few parsing conflicts 280 term.Rule = Id | string_literal | number | funCall | tuple | parSelectStmt;// | inStmt; 281 tuple.Rule = "(" + exprList + ")"; 282 parSelectStmt.Rule = "(" + selectStmt + ")"; 283 unExpr.Rule = unOp + term; 284 unOp.Rule = NOT | "+" | "-" | "~"; 285 binExpr.Rule = expression + binOp + expression; 286 binOp.Rule = ToTerm("+") | "-" | "*" | "/" | "%" //arithmetic 287 | "&" | "|" | "^" |"&&"|"||" //bit 288 | "=" | ">" | "<" | ">=" | "<=" | "<>" | "!=" | "!<" | "!>" 289 | "AND" | "OR" | "LIKE" | NOT + "LIKE" | "IN" | NOT + "IN" |ToTerm("is")| ToTerm("is")+NOT; 290 betweenExpr.Rule = expression + notOpt + "BETWEEN" + expression + "AND" + expression; 291 notOpt.Rule = Empty | NOT; 292 //funCall covers some psedo-operators and special forms like ANY(...), SOME(...), ALL(...), EXISTS(...), IN(...) 293 funCall.Rule = Id + "(" + funArgs + ")"; 294 funArgs.Rule = selectStmt | exprList; 295 inStmt.Rule = expression + "IN" + "(" + exprList + ")"; 296 297 //Operators 298 RegisterOperators(10, "*", "/", "%"); 299 RegisterOperators(9, "+", "-"); 300 RegisterOperators(8, "=", ">", "<", ">=", "<=", "<>", "!=", "!<", "!>", "LIKE", "IN"); 301 RegisterOperators(7, "^", "&", "|","||","&&"); 302 RegisterOperators(6, NOT); 303 RegisterOperators(5, "AND"); 304 RegisterOperators(4, "OR"); 305 306 MarkPunctuation(",", "(", ")"); 307 MarkPunctuation(asOpt, semiOpt); 308 //Note: we cannot declare binOp as transient because it includes operators "NOT LIKE", "NOT IN" consisting of two tokens. 309 // Transient non-terminals cannot have more than one non-punctuation child nodes. 310 // Instead, we set flag InheritPrecedence on binOp , so that it inherits precedence value from it's children, and this precedence is used 311 // in conflict resolution when binOp node is sitting on the stack 312 base.MarkTransient(stmt, term, asOpt, aliasOpt, stmtLine, expression, unOp, tuple); 313 binOp.SetFlag(TermFlags.InheritPrecedence); 314 315 }//constructor 316 317 }//class 318 }//namespace

浙公网安备 33010602011771号