private static List <string> GetParameterNames(string sql) { List <string> l = new List <string>(); Dictionary <string, bool> dict = new Dictionary <string, bool>(); TokenizedSQL tsql = new TokenizedSQL(sql); int n = tsql.Tokens.Length; for (int i = 0; i < n; i++) { Token t = tsql.Tokens[i]; if (t.ID == TokenID.Colon) { i++; t = tsql.Tokens[i]; Token t0 = t; for (; i < n && tsql.Tokens[i].ID == TokenID.Identifier; t = tsql.Tokens[i++]) { ; } string p = DequoteIdentifier(tsql.Extract(t0, t)); if (!dict.ContainsKey(p)) { l.Add(p); dict.Add(p, true); } } } return(l); }
internal Token(TokenizedSQL owner, TokenKind kind, TokenID identifier, int start, int current) { _owner = owner; Kind = kind; ID = identifier; Start = new TokenPosition(owner, start); End = new TokenPosition(owner, current - 1); }
public override Tuple <int, int> GetWordAt(string sql, int position) { TokenizedSQL tsql = new TokenizedSQL(sql, position); Token sel = tsql.Selected; if (sel == null) { return(null); } return(new Tuple <int, int>(sel.Start.Index, sel.End.Index - sel.Start.Index + 1)); }
public override Tuple <int, int> GetErrorPosition(Exception t, string sql, int offset) { if (!(t is Npgsql.PostgresException)) { return(null); } Npgsql.PostgresException ex = (Npgsql.PostgresException)t; int p0 = ex.Position; if (p0 <= 0) { return(null); } p0--; TokenizedSQL tsql = new TokenizedSQL(sql.Substring(offset)); bool wasColon = false; int seq = 1; Dictionary <string, int> pdict = new Dictionary <string, int>(); foreach (Token token in tsql.Tokens) { if (wasColon && token.Kind == TokenKind.Identifier) { // パラメータは内部的に数字に置換して実行し、 // 置換後のSQLでの文字位置が返るため // そのままでは位置がずれてしまう int idx; if (!pdict.TryGetValue(token.Value, out idx)) { idx = seq++; pdict.Add(token.Value, idx); } p0 += (token.Value.Length - idx.ToString().Length); } wasColon = (token.ID == TokenID.Colon); } int n = sql.Length; int p; for (p = p0; p < n && !char.IsWhiteSpace(sql, p); p++) { ; } if (p0 < offset) { return(null); } return(new Tuple <int, int>(p0 - offset, p - p0)); }
internal Token(TokenizedSQL owner, TokenKind kind, string ids, int start, int current) { _owner = owner; Kind = kind; byte[] bytes = Encoding.ASCII.GetBytes(ids); int v = 0; foreach (byte b in bytes) { v = v << 8 | b; } ID = (TokenID)v; Start = new TokenPosition(owner, start); End = new TokenPosition(owner, current - 1); }
public override SQLParts SplitSQL(string sql) { List <SQLPart> l = new List <SQLPart>(); TokenizedSQL tsql = new TokenizedSQL(sql); int i = 0; int n = tsql.Tokens.Length; while (i < n) { //Token t = tsql.Tokens[i]; for (; i < n; i++) { Token t = tsql.Tokens[i]; if (t.Kind != TokenKind.Space && t.Kind != TokenKind.NewLine && t.Kind != TokenKind.Comment) { break; } } int i0 = i; Token t0 = tsql.Tokens[i0]; bool endByNewLine = false; if (t0.Kind == TokenKind.Identifier && (string.Compare(t0.Value, "begin") == 0 || string.Compare(t0.Value, "start") == 0)) { endByNewLine = true; } for (; i < n && tsql.Tokens[i].Kind != TokenKind.Semicolon && (!endByNewLine || tsql.Tokens[i].Kind != TokenKind.NewLine); i++) { ; } string s = tsql.Extract(t0, tsql.Tokens[i - 1]); SQLPart sp = new SQLPart() { Offset = t0.Start.Index, SQL = s, ParameterNames = GetParameterNames(s).ToArray(), }; l.Add(sp); i++; } return(new SQLParts() { Items = l.ToArray(), ParameterNames = GetParameterNames(sql).ToArray() }); }
public TokenPosition(TokenizedSQL sql, int index) { // 前回の位置情報を使って高速化(可能なら) TokenPosition previous = sql._lastPos; if (index < previous.Index) { previous = Empty; } string text = sql.Sql; Line = previous.Line; Column = previous.Column; Index = previous.Index; int i = Index; int l = Line; int c = Column; int n = Math.Min(index, text.Length - 1); bool wasCR = false; bool wasLF = false; while (i <= n) { char ch = text[i]; if (wasCR && ch != '\n' || wasLF) { l++; c = 1; } Index = i; Line = l; Column = c; i++; c++; if (char.IsSurrogate(ch)) { i++; c++; } wasCR = (ch == '\r'); wasLF = (ch == '\n'); } sql._lastPos = this; }
public static ExprNode Parse(TokenizedSQL sql, Token token, ref int tokenIndex, SyntaxTreeNode prior, SyntaxTreeNode parent) { throw new NotImplementedException(); }
public override string NormalizeSQL(string sql, CaseRule reservedRule, CaseRule identifierRule) { if (string.IsNullOrEmpty(sql)) { return(sql); } StringBuilder buf = new StringBuilder(); TokenizedSQL tsql = new TokenizedSQL(sql); bool wasLanguage = false; bool isSqlDef = false; foreach (Token t in tsql.Tokens) { if (t.Kind == TokenKind.Space || t.Kind == TokenKind.NewLine || t.Kind == TokenKind.Comment) { continue; } if (wasLanguage && t.Kind == TokenKind.Identifier) { string lang = t.Value.ToLower(); if (lang == "plpgsql" || lang == "sql") { isSqlDef = true; break; } } wasLanguage = (t.Kind == TokenKind.Identifier && t.Value.ToLower() == "language"); } bool noQuote = false; Token holdedSpc = null; foreach (Token t in tsql.Tokens) { // 行末の空白を除去 if (holdedSpc != null && t.Kind != TokenKind.NewLine) { buf.Append(holdedSpc.Value); } holdedSpc = null; switch (t.Kind) { case TokenKind.Identifier: if (IsReservedWord(t.Value)) { buf.Append(NormalizeIdentifier(t.Value, reservedRule, true)); } else { buf.Append(NormalizeIdentifier(t.Value, identifierRule, noQuote)); } break; case TokenKind.DefBody: if (isSqlDef) { buf.Append(NormalizeDefBody(t.Value, reservedRule, identifierRule)); } else { buf.Append(t.Value); } break; case TokenKind.Space: // 行末の空白を除去(次のトークンを見て判断) holdedSpc = t; break; case TokenKind.NewLine: // 改行をCRLFに統一 buf.AppendLine(); break; default: buf.Append(t.Value); break; } noQuote = (t.Kind == TokenKind.Operator) && (t.ID == TokenID.Colon); } return(buf.ToString()); }