/// <summary> /// Checks if a when expression is set within the MERGE-statement and resolves it if so /// </summary> private void ResolveWhenExpression(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context) { if (!tokens[fileIndex].Text.Equals("when", StringComparison.InvariantCultureIgnoreCase)) { return; } else { fileIndex++; //skip 'when' } if (tokens[fileIndex].Text.Equals("matched", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; //skip 'matched' if (tokens[fileIndex].Text.Equals("and", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; //skip 'and' SearchConditionResolver.Resolve(tokens, ref fileIndex, context); } if (!tokens[fileIndex].Text.Equals("then", StringComparison.InvariantCultureIgnoreCase)) { throw new InvalidSqlException("WHEN-expression does not contain the THEN-Keyword"); } else { fileIndex++; //skip 'then' ResolveMergeMatched(tokens, ref fileIndex, context); } } else if (tokens[fileIndex].Text.Equals("not", StringComparison.InvariantCultureIgnoreCase)) { fileIndex += 2; //skip 'not matched' if (tokens[fileIndex].Text.Equals("by", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; //skip 'by' if (tokens[fileIndex].Text.Equals("source", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; //skip source if (tokens[fileIndex].Text.Equals("and", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; //skip 'and' SearchConditionResolver.Resolve(tokens, ref fileIndex, context); } if (!tokens[fileIndex].Text.Equals("then", StringComparison.InvariantCultureIgnoreCase)) { throw new InvalidSqlException("WHEN-expression does not contain the THEN-Keyword"); } else { fileIndex++; //skip 'then' ResolveMergeMatched(tokens, ref fileIndex, context); } return; } if (tokens[fileIndex].Text.Equals("target", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; } } if (tokens[fileIndex].Text.Equals("and", StringComparison.InvariantCultureIgnoreCase)) { fileIndex++; //skip 'and' SearchConditionResolver.Resolve(tokens, ref fileIndex, context); } if (!tokens[fileIndex].Text.Equals("then", StringComparison.InvariantCultureIgnoreCase)) { throw new InvalidSqlException("WHEN-expression does not contain the THEN-Keyword"); } else { fileIndex++; //skip 'then' ResolveMergeNotMatched(tokens, ref fileIndex, context); } } else { throw new InvalidSqlException("Invalid WHEN-expression within MERGE-statement"); } }
public DataManipulation Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context) { manipulation = new DataManipulation(); fileIndex++; //skip "merge" //skip top expression SkipTopExpression(tokens, ref fileIndex, context); if (tokens[fileIndex].Text.ToLower().Equals("into")) { fileIndex++; } targetObject = StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context); context.AddDatabaseObjectToCurrentContext(targetObject); if (!tokens[fileIndex].Text.ToLower().Equals("using")) { throw new InvalidSqlException("Trying to resolve a merge-statement without using keyword"); } var source = ResolveUsingStatement(tokens, ref fileIndex, context); context.AddDatabaseObjectToCurrentContext(source); if (!tokens[fileIndex].Text.Equals("on", StringComparison.InvariantCultureIgnoreCase)) { throw new InvalidSqlException("Expected 'ON' keyword when resolving a 'MERGE'-statement"); } fileIndex++; //skip 'on' SearchConditionResolver.Resolve(tokens, ref fileIndex, context); while (tokens[fileIndex].Text.Equals("when", StringComparison.InvariantCultureIgnoreCase)) { ResolveWhenExpression(tokens, ref fileIndex, context); } var beautified = new List <Expression>(); foreach (var exp in manipulation.Expressions) { beautified.Add(Beautifier.BeautifyColumns(exp, context)); } manipulation.Expressions = beautified; while (!tokens[fileIndex].Text.ToLower().Equals(";")) { fileIndex++; if (fileIndex == tokens.Length) { throw new InvalidSqlException("Trying to resolve a merge-statement without proper ';' determination"); } } fileIndex++; //skip ';' context.CurrentDatabaseObjectContext.Pop(); return(manipulation); }
public Expression Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context) { List <Expression> expressions = new List <Expression>(); // The CASE expression has two formats: 'simple' and 'searched'. For more information visit: // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017 bool isSimpleFormat = false; fileIndex++; //skip "case" if (!tokens[fileIndex].Text.ToLower().Equals("when")) { isSimpleFormat = true; StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context); } do { fileIndex++; //skip 'when' if (isSimpleFormat) { StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context); } else { SearchConditionResolver.Resolve(tokens, ref fileIndex, context); } fileIndex++; //skip 'then' Expression thenExpression = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context); if (thenExpression.Type.Equals(ExpressionType.COLUMN)) { expressions.Add(thenExpression); } else if (thenExpression.Type.Equals(ExpressionType.COMPLEX) || thenExpression.Type.Equals(ExpressionType.SCALAR_FUNCTION)) { expressions.AddRange(thenExpression.ChildExpressions); } if (tokens.Length <= fileIndex) { throw new InvalidSqlException("Trying to resolve case-statement without 'end'-keyword"); } if (tokens[fileIndex].Text.ToLower().Equals("when")) { continue; } if (tokens[fileIndex].Text.ToLower().Equals("else")) { fileIndex++; //skip 'else' Expression elseExpression = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context); if (elseExpression.Type.Equals(ExpressionType.COLUMN)) { expressions.Add(elseExpression); } else if (elseExpression.Type.Equals(ExpressionType.COMPLEX) || elseExpression.Type.Equals(ExpressionType.SCALAR_FUNCTION)) { expressions.AddRange(elseExpression.ChildExpressions); } } if (tokens[fileIndex].Text.ToLower().Equals("end")) { fileIndex++; //skip 'end' break; } } while (true); if (expressions.Count == 1) { return(expressions[0]); } else { return(new Expression(ExpressionType.SCALAR_FUNCTION) { Name = "CASE", ChildExpressions = expressions }); } }