Skip to content
Browse files

Added new SqlTokenizer class to support parsing of non-trivial SELECT…

… statements. Modified SqlString.Parse() to ignore parameter references in SQL comments.
  • Loading branch information...
1 parent 3fb22c9 commit 082fe6169f3a05a90b55edc880b30ade01a1abbd @ggeurts ggeurts committed with hazzik
View
1 src/NHibernate.Test/NHibernate.Test.csproj
@@ -1091,6 +1091,7 @@
<Compile Include="ReadOnly\StudentDto.cs" />
<Compile Include="ReadOnly\TextHolder.cs" />
<Compile Include="ReadOnly\VersionedNode.cs" />
+ <Compile Include="SqlCommandTest\SqlTokenizerFixture.cs" />
<Compile Include="Stateless\Contact.cs" />
<Compile Include="Stateless\Country.cs" />
<Compile Include="Stateless\FetchingLazyCollections\LazyCollectionFetchTests.cs" />
View
195 src/NHibernate.Test/SqlCommandTest/SqlTokenizerFixture.cs
@@ -0,0 +1,195 @@
+using NUnit.Framework;
+using NHibernate.SqlCommand;
+using NHibernate.SqlCommand.Parser;
+
+namespace NHibernate.Test.SqlCommandTest
+{
+ [TestFixture]
+ public class SqlTokenizerFixture
+ {
+ [Test]
+ public void TokenizeSimpleSelectStatement()
+ {
+ VerifyTokenizer("SELECT * FROM some_table WHERE key = ? ORDER BY some_field DESC",
+ Text("SELECT"), Whitespace(" "), Text("*"),
+ Whitespace(" "),
+ Text("FROM"), Whitespace(" "), Text("some_table"),
+ Whitespace(" "),
+ Text("WHERE"), Whitespace(" "), Text("key"), Whitespace(" "), Text("="), Whitespace(" "), Parameter(),
+ Whitespace(" "),
+ Text("ORDER"), Whitespace(" "), Text("BY"), Whitespace(" "), Text("some_field"), Whitespace(" "), Text("DESC"));
+ }
+
+ [Test]
+ public void TokenizeLineComments()
+ {
+ VerifyTokenizer("--", Comment("--"));
+ VerifyTokenizer("---", Comment("---"));
+ VerifyTokenizer("--\r", Comment("--"), Whitespace("\r"));
+ VerifyTokenizer("-- Any comment will do",
+ Comment("-- Any comment will do"));
+ VerifyTokenizer("-- Two comments\n--will do too",
+ Comment("-- Two comments"), Whitespace("\n"), Comment("--will do too"));
+ }
+
+ [Test]
+ public void TokenizeBlockComments()
+ {
+ VerifyTokenizer("/**/", Comment("/**/"));
+ VerifyTokenizer("/***/", Comment("/***/"));
+ VerifyTokenizer("/*/*/", Comment("/*/*/"));
+ VerifyTokenizer("/****/", Comment("/****/"));
+ VerifyTokenizer("//**//", Text("/"), Comment("/**/"), Text("/"));
+ VerifyTokenizer("/*\n*/", Comment("/*\n*/"));
+ VerifyTokenizer("/**/\n", Comment("/**/"), Whitespace("\n"));
+ VerifyTokenizer("/**/*", Comment("/**/"), Text("*"));
+ VerifyTokenizer("/**/*/", Comment("/**/"), Text("*/"));
+ VerifyTokenizer("*//**/", Text("*/"), Comment("/**/"));
+ VerifyTokenizer("SELECT/**/*", Text("SELECT"), Comment("/**/"), Text("*"));
+ }
+
+ [Test]
+ public void TokenizeBrackets()
+ {
+ VerifyTokenizer("()", BracketOpen(), BracketClose());
+ VerifyTokenizer("(())", BracketOpen(), BracketOpen(), BracketClose(), BracketClose());
+ VerifyTokenizer("()()", BracketOpen(), BracketClose(), BracketOpen(), BracketClose());
+ VerifyTokenizer("(\n)", BracketOpen(), Whitespace("\n"), BracketClose());
+ VerifyTokenizer("()--()", BracketOpen(), BracketClose(), Comment("--()"));
+ VerifyTokenizer("(--\n)", BracketOpen(), Comment("--"), Whitespace("\n"), BracketClose());
+ VerifyTokenizer("(SELECT)", BracketOpen(), Text("SELECT"), BracketClose());
+
+ VerifyTokenizer("SELECT (SELECT COUNT(*) FROM table), ?",
+ Text("SELECT"), Whitespace(" "),
+ BracketOpen(),
+ Text("SELECT"), Whitespace(" "), Text("COUNT"),
+ BracketOpen(),
+ Text("*"),
+ BracketClose(),
+ Whitespace(" "), Text("FROM"), Whitespace(" "), Text("table"),
+ BracketClose(),
+ Comma(), Whitespace(" "), Parameter());
+ }
+
+ [Test]
+ public void TokenizeQuotedString()
+ {
+ VerifyTokenizer("''", DelimitedText("''"));
+ VerifyTokenizer("''''", DelimitedText("''''"));
+ VerifyTokenizer("'string literal'", DelimitedText("'string literal'"));
+ VerifyTokenizer("'x''s value'", DelimitedText("'x''s value'"));
+ }
+
+ [Test]
+ public void TokenizeQuotedIdentifier()
+ {
+ VerifyTokenizer(@"""Identifier""", DelimitedText(@"""Identifier"""));
+ VerifyTokenizer(@"""""""Identifier""""""", DelimitedText(@"""""""Identifier"""""""));
+ VerifyTokenizer("[Identifier]", DelimitedText("[Identifier]"));
+ VerifyTokenizer("[[Identifier]]]", DelimitedText("[[Identifier]]]"));
+ }
+
+ [Test]
+ public void TokenizeParameters()
+ {
+ VerifyTokenizer("?", Parameter());
+ VerifyTokenizer("'?'", DelimitedText("'?'"));
+ VerifyTokenizer(@"""?""", DelimitedText(@"""?"""));
+ VerifyTokenizer("[?]", DelimitedText("[?]"));
+ VerifyTokenizer("--?", Comment("--?"));
+ VerifyTokenizer("/*?*/", Comment("/*?*/"));
+ VerifyTokenizer("(?)", BracketOpen(), Parameter(), BracketClose());
+ VerifyTokenizer("EXEC InsertSomething ?, ?",
+ Text("EXEC"), Whitespace(" "), Text("InsertSomething"),
+ Whitespace(" "), Parameter(), Comma(),
+ Whitespace(" "), Parameter());
+ }
+
+ private static void VerifyTokenizer(string sql, params ExpectedToken[] expectedTokens)
+ {
+ var sqlString = SqlString.Parse(sql);
+
+ int tokenIndex = 0;
+ int sqlIndex = 0;
+ foreach (var token in new SqlTokenizer(sqlString) { IgnoreComments = false, IgnoreWhitespace = false })
+ {
+ if (tokenIndex >= expectedTokens.Length)
+ {
+ Assert.Fail("Tokenizer returns more than expected '{0}' tokens. \nSQL: {1}\nLast Token: {2}({3})",
+ expectedTokens.Length, sql, token.TokenType, token.Value);
+ }
+
+ var expectedToken = expectedTokens[tokenIndex];
+ Assert.That(token.TokenType, Is.EqualTo(expectedToken.TokenType), "[Token #{0} in '{1}']TokenType", tokenIndex, sql);
+ Assert.That(token.Value, Is.EqualTo(expectedToken.Value), "[Token #{0} in {1}]Value", tokenIndex, sql);
+ Assert.That(token.SqlIndex, Is.EqualTo(sqlIndex), "[Token #{0} in {1}]SqlIndex", tokenIndex, sql);
+ Assert.That(token.Length, Is.EqualTo(expectedToken.Length), "[Token #{0} in {1}]Length", tokenIndex, sql);
+
+ tokenIndex++;
+ sqlIndex += expectedToken.Length;
+ }
+
+ if (tokenIndex < expectedTokens.Length)
+ {
+ Assert.Fail("Tokenizer returns less than expected '{0}' tokens.\nSQL: {1}", expectedTokens.Length, sql);
+ }
+ }
+
+ private static ExpectedToken Comma()
+ {
+ return new ExpectedToken(SqlTokenType.Comma, ",");
+ }
+
+ private static ExpectedToken Parameter()
+ {
+ return new ExpectedToken(SqlTokenType.Parameter, "?");
+ }
+
+ private static ExpectedToken BracketOpen()
+ {
+ return new ExpectedToken(SqlTokenType.BracketOpen, "(");
+ }
+
+ private static ExpectedToken BracketClose()
+ {
+ return new ExpectedToken(SqlTokenType.BracketClose, ")");
+ }
+
+ private static ExpectedToken DelimitedText(string text)
+ {
+ return new ExpectedToken(SqlTokenType.DelimitedText, text);
+ }
+
+ private static ExpectedToken Text(string text)
+ {
+ return new ExpectedToken(SqlTokenType.Text, text);
+ }
+
+ private static ExpectedToken Comment(string text)
+ {
+ return new ExpectedToken(SqlTokenType.Comment, text);
+ }
+
+ private static ExpectedToken Whitespace(string text)
+ {
+ return new ExpectedToken(SqlTokenType.Whitespace, text);
+ }
+
+ private class ExpectedToken
+ {
+ public SqlTokenType TokenType { get; private set; }
+ public string Value { get; private set; }
+
+ public ExpectedToken(SqlTokenType tokenType, string value)
+ {
+ this.TokenType = tokenType;
+ this.Value = value;
+ }
+
+ public int Length
+ {
+ get { return this.Value != null ? this.Value.Length : 0; }
+ }
+ }
+ }
+}
View
4 src/NHibernate/NHibernate.csproj
@@ -607,6 +607,8 @@
<Compile Include="SqlCommand\JoinFragment.cs" />
<Compile Include="SqlCommand\OracleJoinFragment.cs" />
<Compile Include="SqlCommand\Parameter.cs" />
+ <Compile Include="SqlCommand\Parser\SqlToken.cs" />
+ <Compile Include="SqlCommand\Parser\SqlTokenType.cs" />
<Compile Include="SqlCommand\QueryJoinFragment.cs" />
<Compile Include="SqlCommand\QuerySelect.cs" />
<Compile Include="SqlCommand\SelectFragment.cs" />
@@ -614,10 +616,12 @@
<Compile Include="SqlCommand\SqlDeleteBuilder.cs" />
<Compile Include="SqlCommand\SqlInsertBuilder.cs" />
<Compile Include="SqlCommand\SqlCommandImpl.cs" />
+ <Compile Include="SqlCommand\Parser\SqlParserUtils.cs" />
<Compile Include="SqlCommand\SqlSelectBuilder.cs" />
<Compile Include="SqlCommand\SqlSimpleSelectBuilder.cs" />
<Compile Include="SqlCommand\SqlString.cs" />
<Compile Include="SqlCommand\SqlStringBuilder.cs" />
+ <Compile Include="SqlCommand\Parser\SqlTokenizer.cs" />
<Compile Include="SqlCommand\SqlUpdateBuilder.cs" />
<Compile Include="SqlCommand\SqlStringHelper.cs" />
<Compile Include="SqlCommand\Template.cs" />
View
99 src/NHibernate/SqlCommand/Parser/SqlParserUtils.cs
@@ -0,0 +1,99 @@
+using NHibernate.Exceptions;
+
+namespace NHibernate.SqlCommand.Parser
+{
+ internal static class SqlParserUtils
+ {
+ public static int ReadDelimitedText(string text, int maxOffset, int offset)
+ {
+ var startOffset = offset;
+ char quoteEndChar;
+
+ // Determine end delimiter
+ var quoteChar = text[offset++];
+ switch (quoteChar)
+ {
+ case '\'':
+ case '"':
+ quoteEndChar = quoteChar;
+ break;
+ case '[':
+ quoteEndChar = ']';
+ break;
+ default:
+ throw new SqlParseException(string.Format("Quoted text cannot start with '{0}' character", text[offset]));
+ }
+
+ // Find end delimiter, but ignore escaped end delimiters
+ while (offset < maxOffset)
+ {
+ if (text[offset++] == quoteEndChar)
+ {
+ if (offset >= maxOffset || text[offset] != quoteEndChar)
+ {
+ // Non-escaped delimiter char
+ return offset - startOffset;
+ }
+
+ // Escaped delimiter char
+ offset++;
+ }
+ }
+
+ throw new SqlParseException(string.Format("Cannot find terminating '{0}' character for quoted text.", quoteEndChar));
+ }
+
+ public static int ReadLineComment(string text, int maxOffset, int offset)
+ {
+ var startOffset = offset;
+
+ offset += 2;
+ for (; offset < maxOffset; offset++)
+ {
+ switch (text[offset])
+ {
+ case '\r':
+ case '\n':
+ return offset - startOffset;
+ }
+ }
+
+ return offset - startOffset;
+ }
+
+ public static int ReadMultilineComment(string text, int maxOffset, int offset)
+ {
+ var startOffset = offset;
+ offset += 2;
+
+ var prevChar = '\0';
+ for (; offset < maxOffset; offset++)
+ {
+ var ch = text[offset];
+ if (ch == '/' && prevChar == '*')
+ {
+ return offset + 1 - startOffset;
+ }
+
+ prevChar = ch;
+ }
+
+ throw new SqlParseException(string.Format("Cannot find terminating '*/' string for multiline comment."));
+ }
+
+ public static int ReadWhitespace(string text, int maxOffset, int offset)
+ {
+ var startOffset = offset;
+
+ offset++;
+ while (offset < maxOffset)
+ {
+ if (!char.IsWhiteSpace(text[offset])) break;
+ offset++;
+ }
+
+ var result = offset - startOffset;
+ return result;
+ }
+ }
+}
View
119 src/NHibernate/SqlCommand/Parser/SqlToken.cs
@@ -0,0 +1,119 @@
+using System;
+
+namespace NHibernate.SqlCommand.Parser
+{
+ /// <summary>
+ /// A SQL query token as returned by <see cref="SqlTokenizer"/>
+ /// </summary>
+ public class SqlToken
+ {
+ private readonly SqlTokenType _tokenType;
+ private readonly SqlString _sql;
+ private readonly int _sqlIndex;
+ private readonly int _length;
+ private string _value;
+
+ public SqlToken(SqlTokenType tokenType, SqlString sql, int sqlIndex, int length)
+ {
+ _tokenType = tokenType;
+ _sql = sql;
+ _sqlIndex = sqlIndex;
+ _length = length;
+ }
+
+ #region Properties
+
+ public SqlTokenType TokenType
+ {
+ get { return _tokenType; }
+ }
+
+ /// <summary>
+ /// Position at which this token occurs in a <see cref="SqlString"/>.
+ /// </summary>
+ public int SqlIndex
+ {
+ get { return _sqlIndex; }
+ }
+
+ /// <summary>
+ /// Number of characters in this token.
+ /// </summary>
+ public int Length
+ {
+ get { return _length; }
+ }
+
+ public string Value
+ {
+ get { return _value ?? (_value = _sql.ToString(_sqlIndex, _length)); }
+ }
+
+ public string UnquotedValue
+ {
+ get
+ {
+ switch (_tokenType)
+ {
+ case SqlTokenType.DelimitedText:
+ return _length > 2
+ ? this.Value.Substring(2, _length - 2)
+ : string.Empty;
+ default:
+ return this.Value;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Instance methods
+
+ public override bool Equals(object obj)
+ {
+ var other = obj as SqlToken;
+ if (ReferenceEquals(other, null)) return false;
+
+ return _tokenType.Equals(other._tokenType)
+ && _sqlIndex.Equals(other._sqlIndex)
+ && _length.Equals(other._length)
+ && _sql.Equals(other._sql);
+ }
+
+ public override int GetHashCode()
+ {
+ const uint FNV_OFFSET_BASIS = 2166136261;
+ const uint FNV_PRIME = 16777619;
+
+ uint hashCode = FNV_OFFSET_BASIS;
+ unchecked
+ {
+ hashCode ^= (uint)_tokenType;
+ hashCode *= FNV_PRIME;
+ hashCode ^= (uint)_sqlIndex;
+ hashCode *= FNV_PRIME;
+ hashCode ^= (uint)_length;
+ hashCode *= FNV_PRIME;
+ return (int)hashCode;
+ }
+ }
+
+ public bool Equals(string value)
+ {
+ return Equals(value, StringComparison.Ordinal);
+ }
+
+ public bool Equals(string value, StringComparison stringComparison)
+ {
+ return value != null
+ && value.Equals(this.Value, stringComparison);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}({1})", this.TokenType, this.Value);
+ }
+
+ #endregion
+ }
+}
View
71 src/NHibernate/SqlCommand/Parser/SqlTokenType.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace NHibernate.SqlCommand.Parser
+{
+ /// <summary>
+ /// <see cref="SqlToken"/> token types.
+ /// </summary>
+ [Flags]
+ public enum SqlTokenType
+ {
+ /// <summary>
+ /// Whitespace
+ /// </summary>
+ Whitespace = 0x1,
+
+ /// <summary>
+ /// Single line comment (preceeded by --) or multi-line comment (terminated by /* and */)
+ /// </summary>
+ Comment = 0x2,
+
+ /// <summary>
+ /// Keywords, operators or undelimited identifiers.
+ /// </summary>
+ Text = 0x4,
+
+ /// <summary>
+ /// Delimited identifiers or string literals.
+ /// </summary>
+ DelimitedText = 0x8,
+
+ /// <summary>
+ /// A query parameter.
+ /// </summary>
+ Parameter = 0x10,
+
+ /// <summary>
+ /// List separator, the ',' character.
+ /// </summary>
+ Comma = 0x20,
+
+ /// <summary>
+ /// Begin of an expression block, consisting of a '(' character.
+ /// </summary>
+ BracketOpen = 0x40,
+
+ /// <summary>
+ /// End of an expression block, consisting of a ')' character.
+ /// </summary>
+ BracketClose = 0x80,
+
+ /// <summary>
+ /// Tokens for begin or end of expression blocks.
+ /// </summary>
+ AllBrackets = BracketOpen | BracketClose,
+
+ /// <summary>
+ /// Includes all token types except whitespace or comments
+ /// </summary>
+ AllExceptWhitespaceOrComment = AllExceptWhitespace & ~Comment,
+
+ /// <summary>
+ /// Includes all token types except whitespace
+ /// </summary>
+ AllExceptWhitespace = All & ~Whitespace,
+
+ /// <summary>
+ /// Includes all token types
+ /// </summary>
+ All = Whitespace | Comment | Text | Comma | BracketOpen | BracketClose | Parameter | DelimitedText,
+ }
+}
View
157 src/NHibernate/SqlCommand/Parser/SqlTokenizer.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.Collections;
+
+namespace NHibernate.SqlCommand.Parser
+{
+ /// <summary>
+ /// Splits a <see cref="SqlString"/> into <see cref="SqlToken"/>s.
+ /// </summary>
+ public class SqlTokenizer : IEnumerable<SqlToken>
+ {
+ private readonly SqlString _sql;
+ private SqlTokenType _includeTokens = SqlTokenType.AllExceptWhitespaceOrComment;
+
+ public SqlTokenizer(SqlString sql)
+ {
+ if (sql == null) throw new ArgumentNullException("sql");
+ _sql = sql;
+ }
+
+ public bool IgnoreWhitespace
+ {
+ get { return !CanYield(SqlTokenType.Whitespace); }
+ set { Ignore(SqlTokenType.Whitespace, value); }
+ }
+
+ public bool IgnoreComments
+ {
+ get { return !CanYield(SqlTokenType.Comment); }
+ set { Ignore(SqlTokenType.Comment, value); }
+ }
+
+ private bool CanYield(SqlTokenType tokenType)
+ {
+ return (_includeTokens & tokenType) == tokenType;
+ }
+
+ private void Ignore(SqlTokenType tokenType, bool canYield)
+ {
+ _includeTokens = canYield
+ ? _includeTokens & ~tokenType
+ : _includeTokens | tokenType;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<SqlToken> GetEnumerator()
+ {
+ int sqlIndex = 0;
+ foreach (var part in _sql)
+ {
+ var parameter = part as Parameter;
+ if (parameter != null)
+ {
+ if (CanYield(SqlTokenType.Parameter))
+ {
+ yield return new SqlToken(SqlTokenType.Parameter, _sql, sqlIndex, 1);
+ }
+ sqlIndex++;
+ continue;
+ }
+
+ var text = part as string;
+ if (text != null)
+ {
+ int offset = 0;
+ int maxOffset = text.Length;
+ int tokenOffset = 0;
+ SqlTokenType nextTokenType = 0;
+ int nextTokenLength = 0;
+
+ while (offset < maxOffset)
+ {
+ var ch = text[offset];
+ switch (ch)
+ {
+ case '(':
+ nextTokenType = SqlTokenType.BracketOpen;
+ nextTokenLength = 1;
+ break;
+ case ')':
+ nextTokenType = SqlTokenType.BracketClose;
+ nextTokenLength = 1;
+ break;
+ case '\'': // String literals
+ case '\"': // ANSI quoted identifiers
+ case '[': // Sql Server quoted indentifiers
+ nextTokenType = SqlTokenType.DelimitedText;
+ nextTokenLength = SqlParserUtils.ReadDelimitedText(text, maxOffset, offset);
+ break;
+ case ',':
+ nextTokenType = SqlTokenType.Comma;
+ nextTokenLength = 1;
+ break;
+ case '/':
+ if (offset + 1 < maxOffset && text[offset + 1] == '*')
+ {
+ nextTokenType = SqlTokenType.Comment;
+ nextTokenLength = SqlParserUtils.ReadMultilineComment(text, maxOffset, offset);
+ }
+ break;
+ case '-':
+ if (offset + 1 < maxOffset && text[offset + 1] == '-')
+ {
+ nextTokenType = SqlTokenType.Comment;
+ nextTokenLength = SqlParserUtils.ReadLineComment(text, maxOffset, offset);
+ }
+ break;
+ default:
+ if (char.IsWhiteSpace(ch))
+ {
+ nextTokenType = SqlTokenType.Whitespace;
+ nextTokenLength = SqlParserUtils.ReadWhitespace(text, maxOffset, offset);
+ }
+ break;
+ }
+
+ if (nextTokenType != 0)
+ {
+ if (offset > tokenOffset)
+ {
+ if (CanYield(SqlTokenType.Text))
+ {
+ yield return new SqlToken(SqlTokenType.Text, _sql, sqlIndex + tokenOffset, offset - tokenOffset);
+ }
+ }
+
+ if (CanYield(nextTokenType))
+ {
+ yield return new SqlToken(nextTokenType, _sql, sqlIndex + offset, nextTokenLength);
+ }
+
+ offset += nextTokenLength;
+ tokenOffset = offset;
+
+ nextTokenType = 0;
+ nextTokenLength = 0;
+ }
+ else
+ {
+ offset++;
+ }
+ }
+
+ if (maxOffset > tokenOffset && CanYield(SqlTokenType.Text))
+ {
+ yield return new SqlToken(SqlTokenType.Text, _sql, sqlIndex + tokenOffset, maxOffset - tokenOffset);
+ }
+ sqlIndex += maxOffset;
+ }
+ }
+ }
+ }
+}
View
64 src/NHibernate/SqlCommand/SqlString.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Collections;
+using NHibernate.SqlCommand.Parser;
using System.Text.RegularExpressions;
namespace NHibernate.SqlCommand
@@ -230,47 +231,58 @@ private SqlString(IEnumerable<object> parts)
/// </remarks>
public static SqlString Parse(string sql)
{
- var result = new SqlStringBuilder();
- var content = new StringBuilder();
+ return new SqlString(ParseParts(sql));
+ }
+
+ private static IEnumerable<object> ParseParts(string text)
+ {
+ if (string.IsNullOrEmpty(text)) yield break;
+
+ int offset = 0;
+ int maxOffset = text.Length;
+ int partOffset = 0;
- bool inQuote = false;
- foreach (char ch in sql)
+ while (offset < maxOffset)
{
+ var ch = text[offset];
switch (ch)
{
- case '?':
- if (inQuote)
+ case '?': // Parameter marker
+ if (offset > partOffset)
{
- content.Append(ch);
+ yield return text.Substring(partOffset, offset - partOffset);
}
- else
+ yield return Parameter.Placeholder;
+ partOffset = offset += 1;
+ break;
+ case '\'': // String literals
+ case '\"': // ANSI quoted identifiers
+ case '[': // Sql Server quoted indentifiers
+ offset += SqlParserUtils.ReadDelimitedText(text, maxOffset, offset);
+ continue;
+ case '/':
+ if (offset + 1 < maxOffset && text[offset + 1] == '*')
{
- if (content.Length > 0)
- {
- result.Add(content.ToString());
- content.Length = 0;
- }
- result.AddParameter();
+ offset += SqlParserUtils.ReadMultilineComment(text, maxOffset, offset);
+ continue;
}
break;
-
- case '\'':
- inQuote = !inQuote;
- content.Append(ch);
+ case '-':
+ if (offset + 1 < maxOffset && text[offset + 1] == '-')
+ {
+ offset += SqlParserUtils.ReadLineComment(text, maxOffset, offset);
+ continue;
+ }
break;
+ }
- default:
- content.Append(ch);
- break;
+ offset++;
}
- }
- if (content.Length > 0)
+ if (maxOffset > partOffset)
{
- result.Add(content.ToString());
+ yield return text.Substring(partOffset, offset - partOffset);
}
-
- return result.ToSqlString();
}
#endregion

0 comments on commit 082fe61

Please sign in to comment.
Something went wrong with that request. Please try again.