private void AppendCommandReplacingParameterValues(Stream dest, string src, int begin, int length, bool prepare, bool forExtendedQuery)
{
char lastChar = '\0';
TokenType currTokenType = TokenType.None;
char paramMarker = '\0';
int currTokenBeg = begin;
int currTokenLen = 0;
Dictionary<NpgsqlParameter, int> paramOrdinalMap = null;
int end = begin + length;
if (prepare)
{
paramOrdinalMap = new Dictionary<NpgsqlParameter, int>();
for (int i = 0 ; i < parameters.Count ; i++)
{
paramOrdinalMap[parameters[i]] = i + 1;
}
}
for (int currCharOfs = begin ; currCharOfs < end ; currCharOfs++)
{
char ch = src[currCharOfs];
// goto label for character re-evaluation:
ProcessCharacter:
switch (currTokenType)
{
case TokenType.None :
switch (ch)
{
case '\'' :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
}
currTokenType = TokenType.Quoted;
currTokenBeg = currCharOfs;
currTokenLen = 1;
break;
case ':' :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
}
currTokenType = TokenType.Colon;
currTokenBeg = currCharOfs;
currTokenLen = 1;
break;
case '<' :
case '@' :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
}
currTokenType = TokenType.FullTextMatchOp;
currTokenBeg = currCharOfs;
currTokenLen = 1;
break;
default :
currTokenLen++;
break;
}
break;
case TokenType.Param :
if (IsParamNameChar(ch))
{
currTokenLen++;
}
else
{
string paramName = src.Substring(currTokenBeg, currTokenLen);
NpgsqlParameter parameter;
bool wroteParam = false;
if (parameters.TryGetValue(paramName, out parameter))
{
if (
(parameter.Direction == ParameterDirection.Input) ||
(parameter.Direction == ParameterDirection.InputOutput)
)
{
if (prepare)
{
AppendParameterPlaceHolder(dest, parameter, paramOrdinalMap[parameter]);
}
else
{
AppendParameterValue(dest, parameter);
}
}
wroteParam = true;
}
if (! wroteParam)
{
dest.WriteString("{0}{1}", paramMarker, paramName);
}
currTokenType = TokenType.None;
currTokenBeg = currCharOfs;
currTokenLen = 0;
// Re-evaluate this character
goto ProcessCharacter;
}
break;
case TokenType.Quoted :
switch (ch)
{
case '\'' :
currTokenLen++;
break;
default :
if (currTokenLen > 1 && lastChar == '\'')
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
currTokenType = TokenType.None;
currTokenBeg = currCharOfs;
currTokenLen = 0;
// Re-evaluate this character
goto ProcessCharacter;
}
else
{
currTokenLen++;
}
break;
}
break;
case TokenType.Colon :
if (IsParamNameChar(ch))
{
// Switch to parameter name token, include this character.
currTokenType = TokenType.Param;
currTokenBeg = currCharOfs;
currTokenLen = 1;
paramMarker = ':';
}
else
{
// Demote to the unknown token type and continue.
currTokenType = TokenType.None;
currTokenLen++;
}
break;
case TokenType.FullTextMatchOp :
if (lastChar == '@' && IsParamNameChar(ch))
{
// Switch to parameter name token, include this character.
currTokenType = TokenType.Param;
currTokenBeg = currCharOfs;
currTokenLen = 1;
paramMarker = '@';
}
else
{
// Demote to the unknown token type and continue.
currTokenType = TokenType.None;
currTokenLen++;
}
break;
}
lastChar = ch;
}
switch (currTokenType)
{
case TokenType.Param :
string paramName = src.Substring(currTokenBeg, currTokenLen);
NpgsqlParameter parameter;
bool wroteParam = false;
if (parameters.TryGetValue(paramName, out parameter))
{
if (
(parameter.Direction == ParameterDirection.Input) ||
(parameter.Direction == ParameterDirection.InputOutput)
)
{
if (prepare)
{
AppendParameterPlaceHolder(dest, parameter, paramOrdinalMap[parameter]);
}
else
{
AppendParameterValue(dest, parameter);
}
}
wroteParam = true;
}
if (! wroteParam)
{
dest.WriteString("{0}{1}", paramMarker, paramName);
}
break;
default :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
}
break;
}
}