mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-22 09:35:38 -05:00
SqlCmd Connect/On Error/Include commands support (#898)
* Initial Investigation * Working code with include, connect, on error and tests * Adding some loc strings * Some cleanup and more tests * Some dummy change to trigger build * Adding PR comments * Addressing PR comments
This commit is contained in:
@@ -71,7 +71,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
endLine,
|
||||
startColumn + 1,
|
||||
endColumn + 1,
|
||||
batchInfos[0].executionCount
|
||||
batchInfos[0].executionCount,
|
||||
batchInfos[0].sqlCmdCommand
|
||||
);
|
||||
|
||||
batchDefinitionList.Add(batchDef);
|
||||
@@ -100,7 +101,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
endLine,
|
||||
startColumn + 1,
|
||||
endColumn + 1,
|
||||
batchInfos[index].executionCount
|
||||
batchInfos[index].executionCount,
|
||||
batchInfos[index].sqlCmdCommand
|
||||
);
|
||||
batchDefinitionList.Add(batch);
|
||||
}
|
||||
@@ -235,7 +237,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
endLine,
|
||||
startColumn + 1,
|
||||
endColumn + 1,
|
||||
batchInfo.executionCount
|
||||
batchInfo.executionCount,
|
||||
batchInfo.sqlCmdCommand
|
||||
);
|
||||
}
|
||||
|
||||
@@ -381,7 +384,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
}
|
||||
|
||||
// Add the script info
|
||||
batchInfos.Add(new BatchInfo(args.Batch.TextSpan.iStartLine, args.Batch.TextSpan.iStartIndex, batchText, args.Batch.ExpectedExecutionCount));
|
||||
batchInfos.Add(new BatchInfo(args.Batch.TextSpan.iStartLine, args.Batch.TextSpan.iStartIndex, batchText, args.SqlCmdCommand, args.Batch.ExpectedExecutionCount));
|
||||
}
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
@@ -474,17 +477,19 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
|
||||
private class BatchInfo
|
||||
{
|
||||
public BatchInfo(int startLine, int startColumn, string batchText, int repeatCount = 1)
|
||||
public BatchInfo(int startLine, int startColumn, string batchText, SqlCmdCommand sqlCmdCommand, int repeatCount = 1)
|
||||
{
|
||||
this.startLine = startLine;
|
||||
this.startColumn = startColumn;
|
||||
this.executionCount = repeatCount;
|
||||
this.batchText = batchText;
|
||||
this.sqlCmdCommand = sqlCmdCommand;
|
||||
}
|
||||
public int startLine;
|
||||
public int startColumn;
|
||||
public int executionCount;
|
||||
public string batchText;
|
||||
public SqlCmdCommand sqlCmdCommand;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
{
|
||||
public class ConnectSqlCmdCommand : SqlCmdCommand
|
||||
{
|
||||
internal ConnectSqlCmdCommand(string server, string username, string password) : base(LexerTokenType.Connect)
|
||||
{
|
||||
Server = server;
|
||||
UserName = username;
|
||||
Password = password;
|
||||
}
|
||||
|
||||
public string Server { get; private set; }
|
||||
public string UserName { get; private set; }
|
||||
public string Password { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// attempts to establish connection with given params
|
||||
/// </summary>
|
||||
/// <returns>returns the connection object is successful, throws otherwise</returns>
|
||||
public DbConnection Connect()
|
||||
{
|
||||
//create SqlConnectionInfo object
|
||||
SqlConnectionInfo connectionInfo = new SqlConnectionInfo();
|
||||
if (Server != null && Server.Length > 0)
|
||||
{
|
||||
connectionInfo.ServerName = Server;
|
||||
}
|
||||
if (UserName != null && UserName.Length > 0)
|
||||
{
|
||||
connectionInfo.UseIntegratedSecurity = false;
|
||||
connectionInfo.UserName = UserName;
|
||||
connectionInfo.Password = Password;
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionInfo.UseIntegratedSecurity = true;
|
||||
}
|
||||
|
||||
DbConnection dbConnection = AttemptToEstablishCurConnection(connectionInfo);
|
||||
return dbConnection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called when we need to establish new connection for batch executio as a
|
||||
/// result of "connect" command processing
|
||||
/// </summary>
|
||||
/// <param name="ci"></param>
|
||||
/// <returns></returns>
|
||||
private DbConnection AttemptToEstablishCurConnection(SqlConnectionInfo ci)
|
||||
{
|
||||
if (ci == null || ci.ServerName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IDbConnection conn = null;
|
||||
try
|
||||
{
|
||||
string connString = ci.ConnectionString;
|
||||
connString += ";Pooling=false"; //turn off connection pooling (this is done in other tools so following the same pattern)
|
||||
|
||||
conn = new SqlConnection(connString);
|
||||
conn.Open();
|
||||
|
||||
return conn as DbConnection;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to Change connection to {ci.ServerName}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
/// <summary>
|
||||
/// Constructor method for a BatchDefinition
|
||||
/// </summary>
|
||||
public BatchDefinition(string batchText, int startLine, int endLine, int startColumn, int endColumn, int executionCount)
|
||||
public BatchDefinition(string batchText, int startLine, int endLine, int startColumn, int endColumn, int executionCount, SqlCmdCommand command)
|
||||
{
|
||||
BatchText = batchText;
|
||||
StartLine = startLine;
|
||||
@@ -22,6 +22,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
EndColumn = endColumn;
|
||||
// set the batch execution count, with min value of 1
|
||||
BatchExecutionCount = executionCount > 0 ? executionCount : 1;
|
||||
SqlCmdCommand = command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -64,6 +65,11 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SqlCmdCommand SqlCmdCommand
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get number of times to execute this batch
|
||||
/// </summary>
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
public delegate void HaltParserDelegate();
|
||||
public delegate void ScriptMessageDelegate(string message);
|
||||
public delegate void ScriptErrorDelegate(string message, ScriptMessageType messageType);
|
||||
public delegate bool ExecuteDelegate(string batchScript, int num, int lineNumber);
|
||||
public delegate bool ExecuteDelegate(string batchScript, int num, int lineNumber, SqlCmdCommand command);
|
||||
#endregion
|
||||
|
||||
#region Constructors / Destructor
|
||||
@@ -75,7 +75,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
/// <summary>
|
||||
/// Take approptiate action on the parsed batches
|
||||
/// </summary>
|
||||
public BatchParserAction Go(TextBlock batch, int repeatCount)
|
||||
public BatchParserAction Go(TextBlock batch, int repeatCount, SqlCmdCommand command)
|
||||
{
|
||||
string str;
|
||||
LineInfo lineInfo;
|
||||
@@ -85,7 +85,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
bool executeResult = false;
|
||||
if (executeDelegate != null)
|
||||
{
|
||||
executeResult = executeDelegate(str, repeatCount, lineInfo.GetStreamPositionForOffset(0).Line + startingLine - 1);
|
||||
executeResult = executeDelegate(str, repeatCount, lineInfo.GetStreamPositionForOffset(0).Line + startingLine - 1, command);
|
||||
}
|
||||
return executeResult ? BatchParserAction.Continue : BatchParserAction.Abort;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
|
||||
private readonly Batch batch = null;
|
||||
private readonly ScriptExecutionResult result;
|
||||
private readonly SqlCmdCommand sqlCmdCommand;
|
||||
|
||||
private BatchParserExecutionFinishedEventArgs()
|
||||
{
|
||||
@@ -23,10 +24,11 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
/// <summary>
|
||||
/// Constructor method for the class
|
||||
/// </summary>
|
||||
public BatchParserExecutionFinishedEventArgs(ScriptExecutionResult batchResult, Batch batch)
|
||||
public BatchParserExecutionFinishedEventArgs(ScriptExecutionResult batchResult, Batch batch, SqlCmdCommand sqlCmdCommand)
|
||||
{
|
||||
this.batch = batch;
|
||||
result = batchResult;
|
||||
this.sqlCmdCommand = sqlCmdCommand;
|
||||
}
|
||||
|
||||
public Batch Batch
|
||||
@@ -44,5 +46,13 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public SqlCmdCommand SqlCmdCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return sqlCmdCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
private Dictionary<string, string> internalVariables = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
private ConnectionChangedDelegate connectionChangedDelegate;
|
||||
private ErrorActionChangedDelegate errorActionChangedDelegate;
|
||||
|
||||
|
||||
public delegate void ConnectionChangedDelegate(SqlConnectionStringBuilder connectionstringBuilder);
|
||||
public delegate void ErrorActionChangedDelegate(OnErrorAction ea);
|
||||
|
||||
public delegate void ErrorActionChangedDelegate(OnErrorAction ea);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor taking a Parser instance
|
||||
/// </summary>
|
||||
@@ -49,7 +49,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
get { return errorActionChangedDelegate; }
|
||||
set { errorActionChangedDelegate = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Looks for any environment variable or internal variable.
|
||||
/// </summary>
|
||||
@@ -105,17 +105,78 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
get { return internalVariables; }
|
||||
set { internalVariables = value; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "ppIBatchSource")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "fileName")]
|
||||
public override BatchParserAction Include(TextBlock filename, out TextReader stream, out string newFilename)
|
||||
{
|
||||
stream = null;
|
||||
newFilename = null;
|
||||
LineInfo lineInfo;
|
||||
|
||||
RaiseScriptError(string.Format(CultureInfo.CurrentCulture, SR.EE_ExecutionError_CommandNotSupported, "Include"), ScriptMessageType.Error);
|
||||
return BatchParserAction.Abort;
|
||||
if (filename == null)
|
||||
{
|
||||
stream = null;
|
||||
return BatchParserAction.Abort;
|
||||
}
|
||||
|
||||
filename.GetText(resolveVariables: true, text: out newFilename, lineInfo: out lineInfo);
|
||||
string resolvedFileNameWithFullPath = GetFilePath(newFilename);
|
||||
|
||||
if (!File.Exists(resolvedFileNameWithFullPath))
|
||||
{
|
||||
stream = null;
|
||||
return BatchParserAction.Abort;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream = new StreamReader(resolvedFileNameWithFullPath);
|
||||
}
|
||||
return BatchParserAction.Continue;
|
||||
}
|
||||
|
||||
private string GetFilePath(string fileName)
|
||||
{
|
||||
//try appending the file name with current working directory path
|
||||
string fullFileName = null;
|
||||
try
|
||||
{
|
||||
if (Environment.CurrentDirectory != null && !File.Exists(fileName))
|
||||
{
|
||||
string currentWorkingDirectory = Environment.CurrentDirectory;
|
||||
if (currentWorkingDirectory != null)
|
||||
{
|
||||
fullFileName = Path.GetFullPath(Path.Combine(currentWorkingDirectory, fileName));
|
||||
if (!File.Exists(fullFileName))
|
||||
{
|
||||
fullFileName = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (fullFileName == null)
|
||||
{
|
||||
fullFileName = Path.GetFullPath(fileName);
|
||||
}
|
||||
|
||||
return fullFileName;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
//path contains invalid path characters.
|
||||
throw new SqlCmdException(SR.SqlCmd_PathInvalid);
|
||||
}
|
||||
catch (PathTooLongException)
|
||||
{
|
||||
//path is too long
|
||||
throw new SqlCmdException(SR.SqlCmd_PathLong);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//catch all other exceptions and report generic error
|
||||
throw new SqlCmdException(string.Format(SR.SqlCmd_FailedInclude, fileName));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -281,14 +281,14 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
/// </summary>
|
||||
/// <param name="batch"></param>
|
||||
/// <param name="batchResult"></param>
|
||||
private void RaiseBatchParserExecutionFinished(Batch batch, ScriptExecutionResult batchResult)
|
||||
private void RaiseBatchParserExecutionFinished(Batch batch, ScriptExecutionResult batchResult, SqlCmdCommand sqlCmdCommand)
|
||||
{
|
||||
Debug.Assert(batch != null);
|
||||
|
||||
EventHandler<BatchParserExecutionFinishedEventArgs> cache = BatchParserExecutionFinished;
|
||||
if (cache != null)
|
||||
{
|
||||
BatchParserExecutionFinishedEventArgs args = new BatchParserExecutionFinishedEventArgs(batchResult, batch);
|
||||
BatchParserExecutionFinishedEventArgs args = new BatchParserExecutionFinishedEventArgs(batchResult, batch, sqlCmdCommand);
|
||||
cache(this, args);
|
||||
}
|
||||
}
|
||||
@@ -336,7 +336,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
private bool ExecuteBatchInternal(
|
||||
string batchScript,
|
||||
int num,
|
||||
int lineNumber)
|
||||
int lineNumber,
|
||||
SqlCmdCommand sqlCmdCommand)
|
||||
{
|
||||
if (lineNumber == -1)
|
||||
{
|
||||
@@ -353,7 +354,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
{
|
||||
bool continueProcessing = true;
|
||||
numBatchExecutionTimes = num;
|
||||
ExecuteBatchTextSpanInternal(batchScript, localTextSpan, out continueProcessing);
|
||||
ExecuteBatchTextSpanInternal(batchScript, localTextSpan, out continueProcessing, sqlCmdCommand);
|
||||
return continueProcessing;
|
||||
}
|
||||
else
|
||||
@@ -368,7 +369,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
/// <param name="batchScript"></param>
|
||||
/// <param name="textSpan"></param>
|
||||
/// <param name="continueProcessing"></param>
|
||||
private void ExecuteBatchTextSpanInternal(string batchScript, TextSpan textSpan, out bool continueProcessing)
|
||||
private void ExecuteBatchTextSpanInternal(string batchScript, TextSpan textSpan, out bool continueProcessing, SqlCmdCommand sqlCmdCommand)
|
||||
{
|
||||
Debug.Assert(!String.IsNullOrEmpty(batchScript));
|
||||
continueProcessing = true;
|
||||
@@ -443,7 +444,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
|
||||
if (!isExecutionDiscarded)
|
||||
{
|
||||
RaiseBatchParserExecutionFinished(currentBatch, batchResult);
|
||||
RaiseBatchParserExecutionFinished(currentBatch, batchResult, sqlCmdCommand);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -501,7 +502,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteBatchInternal(script, /* num */ 1, /* lineNumber */ 0);
|
||||
ExecuteBatchInternal(script, num: 1, lineNumber: 0, /* sqlcmdCommand required for parsing only*/ sqlCmdCommand: null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
{
|
||||
public interface ICommandHandler
|
||||
{
|
||||
BatchParserAction Go(TextBlock batch, int repeatCount);
|
||||
BatchParserAction Go(TextBlock batch, int repeatCount, SqlCmdCommand tokenType);
|
||||
BatchParserAction OnError(Token token, OnErrorAction action);
|
||||
BatchParserAction Include(TextBlock filename, out TextReader stream, out string newFilename);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
{
|
||||
public class OnErrorSqlCmdCommand : SqlCmdCommand
|
||||
{
|
||||
internal OnErrorSqlCmdCommand(OnErrorAction action) : base(LexerTokenType.OnError)
|
||||
{
|
||||
Action = action;
|
||||
}
|
||||
|
||||
public OnErrorAction Action { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
private Lexer lexer;
|
||||
private List<Token> tokenBuffer;
|
||||
private readonly IVariableResolver variableResolver;
|
||||
private SqlCmdCommand sqlCmdCommand;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the Parser class
|
||||
@@ -126,7 +127,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
if (state == 0 && ch == '$')
|
||||
{
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
else if (state == 1)
|
||||
{
|
||||
if (ch == '(')
|
||||
@@ -200,7 +201,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
private void ExecuteBatch(int repeatCount)
|
||||
{
|
||||
BatchParserAction action;
|
||||
action = commandHandler.Go(new TextBlock(this, tokenBuffer), repeatCount);
|
||||
action = commandHandler.Go(new TextBlock(this, tokenBuffer), repeatCount, this.sqlCmdCommand);
|
||||
|
||||
if (action == BatchParserAction.Abort)
|
||||
{
|
||||
@@ -292,8 +293,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
if (tokenText.IndexOf('"') != -1)
|
||||
{
|
||||
tokens = SplitQuotedTextToken(token);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens = new[] { token };
|
||||
}
|
||||
@@ -348,7 +349,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
tokens.Add(GetSubToken(token, quotePos + 1, closingQuotePos, LexerTokenType.TextVerbatim));
|
||||
}
|
||||
offset = closingQuotePos + 1;
|
||||
|
||||
|
||||
quotePos = tokenText.IndexOf('"', offset);
|
||||
}
|
||||
if (offset != tokenText.Length)
|
||||
@@ -406,6 +407,11 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
ParseSetvar(setvarToken);
|
||||
break;
|
||||
case LexerTokenType.Connect:
|
||||
Token connectToken = LookaheadToken;
|
||||
RemoveLastWhitespaceToken();
|
||||
Accept();
|
||||
ParseConnect(connectToken);
|
||||
break;
|
||||
case LexerTokenType.Ed:
|
||||
case LexerTokenType.ErrorCommand:
|
||||
case LexerTokenType.Execute:
|
||||
@@ -472,6 +478,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
|
||||
parserAction = commandHandler.OnError(onErrorToken, onErrorAction);
|
||||
|
||||
this.sqlCmdCommand = new OnErrorSqlCmdCommand(onErrorAction);
|
||||
|
||||
if (parserAction == BatchParserAction.Abort)
|
||||
{
|
||||
RaiseError(ErrorCode.Aborted);
|
||||
@@ -522,6 +530,83 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
variableResolver.SetVariable(setvarToken.Begin, variableName, variableValue);
|
||||
}
|
||||
|
||||
|
||||
private void ParseConnect(Token connectToken)
|
||||
{
|
||||
string serverName = null;
|
||||
string userName = null;
|
||||
string password = null;
|
||||
Accept(LexerTokenType.Whitespace);
|
||||
Expect(LexerTokenType.Text);
|
||||
|
||||
serverName = ResolveVariables(LookaheadToken, 0, null);
|
||||
if (serverName == null)
|
||||
{
|
||||
//found some text but couldn't parse for servername
|
||||
RaiseError(ErrorCode.UnrecognizedToken);
|
||||
}
|
||||
|
||||
Accept();
|
||||
Accept(LexerTokenType.Whitespace);
|
||||
|
||||
switch (LookaheadTokenType)
|
||||
{
|
||||
case LexerTokenType.Text:
|
||||
userName = ParseUserName();
|
||||
password = ParsePassword();
|
||||
if(userName == null || password == null)
|
||||
{
|
||||
//found some text but couldn't parse for user/password
|
||||
RaiseError(ErrorCode.UnrecognizedToken);
|
||||
}
|
||||
break;
|
||||
case LexerTokenType.NewLine:
|
||||
case LexerTokenType.Eof:
|
||||
Accept();
|
||||
break;
|
||||
default:
|
||||
RaiseError(ErrorCode.UnrecognizedToken);
|
||||
break;
|
||||
}
|
||||
|
||||
this.sqlCmdCommand = new ConnectSqlCmdCommand(serverName, userName, password);
|
||||
|
||||
}
|
||||
|
||||
private string ParseUserName()
|
||||
{
|
||||
string username = null;
|
||||
if (LookaheadToken.Text == "-U")
|
||||
{
|
||||
Accept();
|
||||
Accept(LexerTokenType.Whitespace);
|
||||
if (LookaheadTokenType == LexerTokenType.Text)
|
||||
{
|
||||
username = ResolveVariables(LookaheadToken, 0, null);
|
||||
Accept();
|
||||
Accept(LexerTokenType.Whitespace);
|
||||
}
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
private string ParsePassword()
|
||||
{
|
||||
string password = null;
|
||||
if (LookaheadToken.Text == "-P")
|
||||
{
|
||||
Accept();
|
||||
Accept(LexerTokenType.Whitespace);
|
||||
if (LookaheadTokenType == LexerTokenType.Text)
|
||||
{
|
||||
password = ResolveVariables(LookaheadToken, 0, null);
|
||||
Accept();
|
||||
Accept(LexerTokenType.Whitespace);
|
||||
}
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
||||
internal void RaiseError(ErrorCode errorCode, string message = null)
|
||||
{
|
||||
RaiseError(errorCode, LookaheadToken, message);
|
||||
@@ -558,8 +643,8 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
|
||||
if (variablePos != null)
|
||||
{
|
||||
LineInfo.CalculateLineColumnForOffset(inputToken.Text, reference.Start - offset,
|
||||
variablePos.Value.Offset, variablePos.Value.Line, variablePos.Value.Column,
|
||||
LineInfo.CalculateLineColumnForOffset(inputToken.Text, reference.Start - offset,
|
||||
variablePos.Value.Offset, variablePos.Value.Line, variablePos.Value.Column,
|
||||
out line, out column);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to pass back SqlCmd specific properties from Parser to Query Execution
|
||||
/// </summary>
|
||||
public class SqlCmdCommand
|
||||
{
|
||||
internal SqlCmdCommand(LexerTokenType tokenType)
|
||||
{
|
||||
this.LexerTokenType = tokenType;
|
||||
}
|
||||
|
||||
public LexerTokenType LexerTokenType { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Specific exception type for SQLCMD related issues
|
||||
/// </summary>
|
||||
public class SqlCmdException : Exception
|
||||
{
|
||||
public SqlCmdException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user