PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/SmarterSql/SmarterSql/Parsing/Keywords/KeywordUpdate.cs

#
C# | 223 lines | 147 code | 21 blank | 55 comment | 87 complexity | 519523c5b88af4c3e127c3943f9808a2 MD5 | raw file
  1. // ---------------------------------
  2. // SmarterSql (c) Johan Sassner 2008
  3. // ---------------------------------
  4. using System.Collections.Generic;
  5. using Sassner.SmarterSql.Objects;
  6. using Sassner.SmarterSql.Parsing.Expressions;
  7. using Sassner.SmarterSql.ParsingUtils;
  8. using Sassner.SmarterSql.Tree;
  9. using Sassner.SmarterSql.Utils;
  10. namespace Sassner.SmarterSql.Parsing.Keywords {
  11. public class KeywordUpdate {
  12. #region Parse UPDATE
  13. /// <summary>
  14. /// UPDATE
  15. /// [ TOP ( expression ) [ PERCENT ] ]
  16. /// { <object> | rowset_function_limited
  17. /// [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
  18. /// }
  19. /// SET
  20. /// { column_name = { expression | DEFAULT | NULL }
  21. /// | { udt_column_name.{ { property_name = expression
  22. /// | field_name = expression }
  23. /// | method_name ( argument [ ,...n ] )
  24. /// }
  25. /// }
  26. /// | column_name { .WRITE ( expression , @Offset , @Length ) }
  27. /// | @variable = expression
  28. /// | @variable = column = expression [ ,...n ]
  29. /// } [ ,...n ]
  30. /// [ <OUTPUT Clause> ]
  31. /// [FROM] ....
  32. /// </summary>
  33. /// <param name="parser"></param>
  34. /// <param name="currentStartSpan"></param>
  35. /// <param name="lstSysObjects"></param>
  36. /// <param name="i"></param>
  37. /// <param name="lstTokens"></param>
  38. public static void ParseUpdateStatement(Parser parser, out StatementSpans currentStartSpan, List<SysObject> lstSysObjects, ref int i, List<TokenInfo> lstTokens) {
  39. currentStartSpan = parser.SegmentUtils.GetStatementSpan(i);
  40. if (null == currentStartSpan) {
  41. return;
  42. }
  43. int startIndex = i;
  44. TokenInfo nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  45. if (null != nextToken && nextToken.Kind == TokenKind.KeywordUpdate) {
  46. i++;
  47. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  48. // Handle: [ TOP ( expression ) [ PERCENT ] ]
  49. if (null != nextToken && nextToken.Kind == TokenKind.KeywordTop) {
  50. i++;
  51. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  52. if (null != nextToken && nextToken.Kind == TokenKind.LeftParenthesis && -1 != nextToken.MatchingParenToken && i < nextToken.MatchingParenToken) {
  53. i = InStatement.GetNextNonCommentToken(lstTokens, nextToken.MatchingParenToken + 1, nextToken.MatchingParenToken + 1);
  54. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  55. if (null != nextToken && nextToken.Kind == TokenKind.KeywordPercent) {
  56. i = InStatement.GetNextNonCommentToken(lstTokens, i + 1, i + 1);
  57. }
  58. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  59. }
  60. }
  61. string servername = "";
  62. string databasename = "";
  63. string schemaname = "";
  64. string objectname = "";
  65. TokenInfo tokenStart = null;
  66. int endTableIndex = 0;
  67. int startTableIndex = 0;
  68. int endIndex;
  69. // Handle: { <object> [ WITH ( <Table_Hint_Limited> [ ...n ] ) ] }
  70. if (null != nextToken) {
  71. if (nextToken.Kind == TokenKind.Name || nextToken.Kind == TokenKind.TemporaryObject || nextToken.Kind == TokenKind.Variable) {
  72. TokenInfo server_name;
  73. TokenInfo database_name;
  74. TokenInfo schema_name;
  75. TokenInfo object_name;
  76. startTableIndex = i;
  77. if (parser.ParseTableOrViewName(startTableIndex, out endIndex, out server_name, out database_name, out schema_name, out object_name)) {
  78. servername = (null != server_name ? server_name.Token.UnqoutedImage : "");
  79. databasename = (null != database_name ? database_name.Token.UnqoutedImage : "");
  80. schemaname = (null != schema_name ? schema_name.Token.UnqoutedImage : "");
  81. objectname = (null != object_name ? object_name.Token.UnqoutedImage : "");
  82. tokenStart = ((server_name ?? database_name) ?? schema_name) ?? object_name;
  83. if (null == tokenStart) {
  84. return;
  85. }
  86. if (nextToken.Kind == TokenKind.Variable) {
  87. parser.CalledLocalVariables.Add(new LocalVariable(nextToken.Token.UnqoutedImage, startTableIndex));
  88. }
  89. endTableIndex = endIndex;
  90. i = endIndex;
  91. // Handle: [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
  92. int offset = i;
  93. nextToken = InStatement.GetNextNonCommentToken(lstTokens, offset + 1);
  94. if (null != nextToken && nextToken.Kind == TokenKind.KeywordWith) {
  95. offset++;
  96. nextToken = InStatement.GetNextNonCommentToken(lstTokens, offset + 1);
  97. if (null != nextToken && nextToken.Kind == TokenKind.LeftParenthesis && -1 != nextToken.MatchingParenToken && i < nextToken.MatchingParenToken) {
  98. i = InStatement.GetNextNonCommentToken(lstTokens, nextToken.MatchingParenToken, nextToken.MatchingParenToken);
  99. // TODO: Verify that it's only members from <Table_Hint_Limited> here
  100. }
  101. }
  102. }
  103. } else {
  104. // TODO: Handle: { rowset_function_limited [ WITH ( <Table_Hint_Limited> [ ...n ] ) ] }
  105. }
  106. }
  107. // SET
  108. //* { column_name = { expression | DEFAULT | NULL }
  109. // | { udt_column_name.{ { property_name = expression
  110. // | field_name = expression
  111. // }
  112. // | method_name ( argument [ ,...n ] )
  113. // }
  114. // }
  115. // | column_name { .WRITE ( expression , @Offset , @Length ) }
  116. //* | @variable = expression
  117. // | @variable = column = expression [ ,...n ]
  118. // } [ ,...n ]
  119. i++;
  120. List<Expression> setExpressions = new List<Expression>();
  121. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  122. if (null != tokenStart && null != nextToken && nextToken.Kind == TokenKind.KeywordSet) {
  123. endIndex = currentStartSpan.EndIndex;
  124. while (i < endIndex) {
  125. i++;
  126. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  127. if (null == nextToken) {
  128. break;
  129. }
  130. if (nextToken.Kind == TokenKind.Name || nextToken.Kind == TokenKind.TemporaryObject) {
  131. // column_name = { expression | DEFAULT | NULL }
  132. Expression expression;
  133. if (!Expression.FindExpression(parser, lstTokens, ref i, endIndex, out expression)) {
  134. break;
  135. }
  136. setExpressions.Add(expression);
  137. } else if (nextToken.Kind == TokenKind.Variable) {
  138. // @variable = expression
  139. nextToken.TokenContextType = TokenContextType.Variable;
  140. Expression expression;
  141. if (!Expression.FindExpression(parser, lstTokens, ref i, endIndex, out expression)) {
  142. break;
  143. }
  144. setExpressions.Add(expression);
  145. }
  146. i++;
  147. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  148. if (null == nextToken || nextToken.Kind != TokenKind.Comma) {
  149. break;
  150. }
  151. }
  152. if (i < endIndex) {
  153. // Parse rest of the UPDATE statement
  154. nextToken = InStatement.GetNextNonCommentToken(lstTokens, ref i);
  155. if (null != nextToken) {
  156. parser.ParseTokenRange(currentStartSpan, i, endIndex, lstSysObjects);
  157. }
  158. }
  159. SysObject addedSysObject;
  160. TableSource addedTableSource;
  161. parser.CreateTableEntry(currentStartSpan, Tokens.kwUpdateToken, lstSysObjects, servername, databasename, schemaname, objectname, "", startIndex, endIndex, startTableIndex, endTableIndex, false, out addedSysObject, out addedTableSource);
  162. List<TableSource> foundTableSources;
  163. if (parser.SegmentUtils.GetUniqueStatementSpanTablesources(currentStartSpan, out foundTableSources, false)) {
  164. Connection connection = Instance.TextEditor.ActiveConnection;
  165. foreach (Expression expression in setExpressions) {
  166. Expression.GetParsedDataType(connection, lstSysObjects, foundTableSources, expression);
  167. }
  168. }
  169. i = endIndex;
  170. }
  171. }
  172. }
  173. #endregion
  174. #region Parse CURRENT OF
  175. /// <summary>
  176. /// { [ CURRENT OF { { [ GLOBAL ] cursor_name } | cursor_variable_name } ] }
  177. /// </summary>
  178. /// <param name="parser"></param>
  179. /// <param name="lstTokens"></param>
  180. /// <param name="startIndex"></param>
  181. /// <param name="endIndex"></param>
  182. public static bool ParseCurrentOf(Parser parser, List<TokenInfo> lstTokens, int startIndex, int endIndex) {
  183. TokenInfo token = InStatement.GetNextNonCommentToken(lstTokens, startIndex);
  184. if (null == token || token.Kind != TokenKind.KeywordCurrent) {
  185. return false;
  186. }
  187. if (!InStatement.GetIfAllNextValidToken(lstTokens, ref startIndex, out token, TokenKind.KeywordOf)) {
  188. return false;
  189. }
  190. InStatement.GetIfAllNextValidToken(lstTokens, ref startIndex, out token, TokenKind.KeywordGlobal);
  191. startIndex++;
  192. token = InStatement.GetNextNonCommentToken(lstTokens, startIndex);
  193. if (null != token && (token.Kind == TokenKind.Name || token.Kind == TokenKind.Variable)) {
  194. token.TokenContextType = TokenContextType.Cursor;
  195. parser.CalledCursors.Add(new Cursor(token.Token.UnqoutedImage, startIndex));
  196. return true;
  197. }
  198. return false;
  199. }
  200. #endregion
  201. }
  202. }