|
| 1 | +using NUnit.Framework; |
| 2 | +using NHibernate.SqlCommand; |
| 3 | +using NHibernate.SqlCommand.Parser; |
| 4 | + |
| 5 | +namespace NHibernate.Test.SqlCommandTest |
| 6 | +{ |
| 7 | + [TestFixture] |
| 8 | + public class SqlTokenizerFixture |
| 9 | + { |
| 10 | + [Test] |
| 11 | + public void TokenizeSimpleSelectStatement() |
| 12 | + { |
| 13 | + VerifyTokenizer("SELECT * FROM some_table WHERE key = ? ORDER BY some_field DESC", |
| 14 | + Text("SELECT"), Whitespace(" "), Text("*"), |
| 15 | + Whitespace(" "), |
| 16 | + Text("FROM"), Whitespace(" "), Text("some_table"), |
| 17 | + Whitespace(" "), |
| 18 | + Text("WHERE"), Whitespace(" "), Text("key"), Whitespace(" "), Text("="), Whitespace(" "), Parameter(), |
| 19 | + Whitespace(" "), |
| 20 | + Text("ORDER"), Whitespace(" "), Text("BY"), Whitespace(" "), Text("some_field"), Whitespace(" "), Text("DESC")); |
| 21 | + } |
| 22 | + |
| 23 | + [Test] |
| 24 | + public void TokenizeLineComments() |
| 25 | + { |
| 26 | + VerifyTokenizer("--", Comment("--")); |
| 27 | + VerifyTokenizer("---", Comment("---")); |
| 28 | + VerifyTokenizer("--\r", Comment("--"), Whitespace("\r")); |
| 29 | + VerifyTokenizer("-- Any comment will do", |
| 30 | + Comment("-- Any comment will do")); |
| 31 | + VerifyTokenizer("-- Two comments\n--will do too", |
| 32 | + Comment("-- Two comments"), Whitespace("\n"), Comment("--will do too")); |
| 33 | + } |
| 34 | + |
| 35 | + [Test] |
| 36 | + public void TokenizeBlockComments() |
| 37 | + { |
| 38 | + VerifyTokenizer("/**/", Comment("/**/")); |
| 39 | + VerifyTokenizer("/***/", Comment("/***/")); |
| 40 | + VerifyTokenizer("/*/*/", Comment("/*/*/")); |
| 41 | + VerifyTokenizer("/****/", Comment("/****/")); |
| 42 | + VerifyTokenizer("//**//", Text("/"), Comment("/**/"), Text("/")); |
| 43 | + VerifyTokenizer("/*\n*/", Comment("/*\n*/")); |
| 44 | + VerifyTokenizer("/**/\n", Comment("/**/"), Whitespace("\n")); |
| 45 | + VerifyTokenizer("/**/*", Comment("/**/"), Text("*")); |
| 46 | + VerifyTokenizer("/**/*/", Comment("/**/"), Text("*/")); |
| 47 | + VerifyTokenizer("*//**/", Text("*/"), Comment("/**/")); |
| 48 | + VerifyTokenizer("SELECT/**/*", Text("SELECT"), Comment("/**/"), Text("*")); |
| 49 | + } |
| 50 | + |
| 51 | + [Test] |
| 52 | + public void TokenizeBrackets() |
| 53 | + { |
| 54 | + VerifyTokenizer("()", BracketOpen(), BracketClose()); |
| 55 | + VerifyTokenizer("(())", BracketOpen(), BracketOpen(), BracketClose(), BracketClose()); |
| 56 | + VerifyTokenizer("()()", BracketOpen(), BracketClose(), BracketOpen(), BracketClose()); |
| 57 | + VerifyTokenizer("(\n)", BracketOpen(), Whitespace("\n"), BracketClose()); |
| 58 | + VerifyTokenizer("()--()", BracketOpen(), BracketClose(), Comment("--()")); |
| 59 | + VerifyTokenizer("(--\n)", BracketOpen(), Comment("--"), Whitespace("\n"), BracketClose()); |
| 60 | + VerifyTokenizer("(SELECT)", BracketOpen(), Text("SELECT"), BracketClose()); |
| 61 | + |
| 62 | + VerifyTokenizer("SELECT (SELECT COUNT(*) FROM table), ?", |
| 63 | + Text("SELECT"), Whitespace(" "), |
| 64 | + BracketOpen(), |
| 65 | + Text("SELECT"), Whitespace(" "), Text("COUNT"), |
| 66 | + BracketOpen(), |
| 67 | + Text("*"), |
| 68 | + BracketClose(), |
| 69 | + Whitespace(" "), Text("FROM"), Whitespace(" "), Text("table"), |
| 70 | + BracketClose(), |
| 71 | + Comma(), Whitespace(" "), Parameter()); |
| 72 | + } |
| 73 | + |
| 74 | + [Test] |
| 75 | + public void TokenizeQuotedString() |
| 76 | + { |
| 77 | + VerifyTokenizer("''", DelimitedText("''")); |
| 78 | + VerifyTokenizer("''''", DelimitedText("''''")); |
| 79 | + VerifyTokenizer("'string literal'", DelimitedText("'string literal'")); |
| 80 | + VerifyTokenizer("'x''s value'", DelimitedText("'x''s value'")); |
| 81 | + } |
| 82 | + |
| 83 | + [Test] |
| 84 | + public void TokenizeQuotedIdentifier() |
| 85 | + { |
| 86 | + VerifyTokenizer(@"""Identifier""", DelimitedText(@"""Identifier""")); |
| 87 | + VerifyTokenizer(@"""""""Identifier""""""", DelimitedText(@"""""""Identifier""""""")); |
| 88 | + VerifyTokenizer("[Identifier]", DelimitedText("[Identifier]")); |
| 89 | + VerifyTokenizer("[[Identifier]]]", DelimitedText("[[Identifier]]]")); |
| 90 | + } |
| 91 | + |
| 92 | + [Test] |
| 93 | + public void TokenizeParameters() |
| 94 | + { |
| 95 | + VerifyTokenizer("?", Parameter()); |
| 96 | + VerifyTokenizer("'?'", DelimitedText("'?'")); |
| 97 | + VerifyTokenizer(@"""?""", DelimitedText(@"""?""")); |
| 98 | + VerifyTokenizer("[?]", DelimitedText("[?]")); |
| 99 | + VerifyTokenizer("--?", Comment("--?")); |
| 100 | + VerifyTokenizer("/*?*/", Comment("/*?*/")); |
| 101 | + VerifyTokenizer("(?)", BracketOpen(), Parameter(), BracketClose()); |
| 102 | + VerifyTokenizer("EXEC InsertSomething ?, ?", |
| 103 | + Text("EXEC"), Whitespace(" "), Text("InsertSomething"), |
| 104 | + Whitespace(" "), Parameter(), Comma(), |
| 105 | + Whitespace(" "), Parameter()); |
| 106 | + } |
| 107 | + |
| 108 | + private static void VerifyTokenizer(string sql, params ExpectedToken[] expectedTokens) |
| 109 | + { |
| 110 | + var sqlString = SqlString.Parse(sql); |
| 111 | + |
| 112 | + int tokenIndex = 0; |
| 113 | + int sqlIndex = 0; |
| 114 | + foreach (var token in new SqlTokenizer(sqlString) { IgnoreComments = false, IgnoreWhitespace = false }) |
| 115 | + { |
| 116 | + if (tokenIndex >= expectedTokens.Length) |
| 117 | + { |
| 118 | + Assert.Fail("Tokenizer returns more than expected '{0}' tokens. \nSQL: {1}\nLast Token: {2}({3})", |
| 119 | + expectedTokens.Length, sql, token.TokenType, token.Value); |
| 120 | + } |
| 121 | + |
| 122 | + var expectedToken = expectedTokens[tokenIndex]; |
| 123 | + Assert.That(token.TokenType, Is.EqualTo(expectedToken.TokenType), "[Token #{0} in '{1}']TokenType", tokenIndex, sql); |
| 124 | + Assert.That(token.Value, Is.EqualTo(expectedToken.Value), "[Token #{0} in {1}]Value", tokenIndex, sql); |
| 125 | + Assert.That(token.SqlIndex, Is.EqualTo(sqlIndex), "[Token #{0} in {1}]SqlIndex", tokenIndex, sql); |
| 126 | + Assert.That(token.Length, Is.EqualTo(expectedToken.Length), "[Token #{0} in {1}]Length", tokenIndex, sql); |
| 127 | + |
| 128 | + tokenIndex++; |
| 129 | + sqlIndex += expectedToken.Length; |
| 130 | + } |
| 131 | + |
| 132 | + if (tokenIndex < expectedTokens.Length) |
| 133 | + { |
| 134 | + Assert.Fail("Tokenizer returns less than expected '{0}' tokens.\nSQL: {1}", expectedTokens.Length, sql); |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + private static ExpectedToken Comma() |
| 139 | + { |
| 140 | + return new ExpectedToken(SqlTokenType.Comma, ","); |
| 141 | + } |
| 142 | + |
| 143 | + private static ExpectedToken Parameter() |
| 144 | + { |
| 145 | + return new ExpectedToken(SqlTokenType.Parameter, "?"); |
| 146 | + } |
| 147 | + |
| 148 | + private static ExpectedToken BracketOpen() |
| 149 | + { |
| 150 | + return new ExpectedToken(SqlTokenType.BracketOpen, "("); |
| 151 | + } |
| 152 | + |
| 153 | + private static ExpectedToken BracketClose() |
| 154 | + { |
| 155 | + return new ExpectedToken(SqlTokenType.BracketClose, ")"); |
| 156 | + } |
| 157 | + |
| 158 | + private static ExpectedToken DelimitedText(string text) |
| 159 | + { |
| 160 | + return new ExpectedToken(SqlTokenType.DelimitedText, text); |
| 161 | + } |
| 162 | + |
| 163 | + private static ExpectedToken Text(string text) |
| 164 | + { |
| 165 | + return new ExpectedToken(SqlTokenType.Text, text); |
| 166 | + } |
| 167 | + |
| 168 | + private static ExpectedToken Comment(string text) |
| 169 | + { |
| 170 | + return new ExpectedToken(SqlTokenType.Comment, text); |
| 171 | + } |
| 172 | + |
| 173 | + private static ExpectedToken Whitespace(string text) |
| 174 | + { |
| 175 | + return new ExpectedToken(SqlTokenType.Whitespace, text); |
| 176 | + } |
| 177 | + |
| 178 | + private class ExpectedToken |
| 179 | + { |
| 180 | + public SqlTokenType TokenType { get; private set; } |
| 181 | + public string Value { get; private set; } |
| 182 | + |
| 183 | + public ExpectedToken(SqlTokenType tokenType, string value) |
| 184 | + { |
| 185 | + this.TokenType = tokenType; |
| 186 | + this.Value = value; |
| 187 | + } |
| 188 | + |
| 189 | + public int Length |
| 190 | + { |
| 191 | + get { return this.Value != null ? this.Value.Length : 0; } |
| 192 | + } |
| 193 | + } |
| 194 | + } |
| 195 | +} |
0 commit comments