Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 86 additions & 93 deletions Npgsql/Npgsql/NpgsqlCommand.Rewrite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,8 @@ private enum TokenType
None,
Quoted,
Param,
Colon
Colon,
FullTextMatchOp
}

/// <summary>
Expand All @@ -579,6 +580,7 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
int currTokenBeg = begin;
int currTokenLen = 0;
Dictionary<NpgsqlParameter, int> paramOrdinalMap = null;
int end = begin + length;

if (prepare)
{
Expand All @@ -590,7 +592,7 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
}
}

for (int currCharOfs = begin ; currCharOfs < begin + length ; currCharOfs++)
for (int currCharOfs = begin ; currCharOfs < end ; currCharOfs++)
{
char ch = src[currCharOfs];

Expand All @@ -602,7 +604,7 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
case TokenType.None :
switch (ch)
{
case '\'':
case '\'' :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
Expand All @@ -615,7 +617,8 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int

break;

case ':':
case ':' :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
}
Expand All @@ -627,20 +630,21 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int

break;

case '@':
case '<' :
case '@' :
if (currTokenLen > 0)
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
}

currTokenType = TokenType.Param;
currTokenType = TokenType.FullTextMatchOp;

currTokenBeg = currCharOfs + 1;
currTokenLen = 0;
paramMarker = '@';
currTokenBeg = currCharOfs;
currTokenLen = 1;

break;

default:
default :
currTokenLen++;

break;
Expand All @@ -656,40 +660,33 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
}
else
{
if (currTokenLen == 0)
{
dest.WriteBytes((byte)ASCIIBytes.Colon);
}
else
{
string paramName = src.Substring(currTokenBeg, currTokenLen);
NpgsqlParameter parameter;
bool wroteParam = false;
string paramName = src.Substring(currTokenBeg, currTokenLen);
NpgsqlParameter parameter;
bool wroteParam = false;

if (parameters.TryGetValue(paramName, out parameter))
if (parameters.TryGetValue(paramName, out parameter))
{
if (
(parameter.Direction == ParameterDirection.Input) ||
(parameter.Direction == ParameterDirection.InputOutput)
)
{
if (
(parameter.Direction == ParameterDirection.Input) ||
(parameter.Direction == ParameterDirection.InputOutput)
)
if (prepare)
{
if (prepare)
{
AppendParameterPlaceHolder(dest, parameter, paramOrdinalMap[parameter]);
}
else
{
AppendParameterValue(dest, parameter);
}
AppendParameterPlaceHolder(dest, parameter, paramOrdinalMap[parameter]);
}
else
{
AppendParameterValue(dest, parameter);
}

wroteParam = true;
}

if (! wroteParam)
{
dest.WriteString("{0}{1}", paramMarker, paramName);
}
wroteParam = true;
}

if (! wroteParam)
{
dest.WriteString("{0}{1}", paramMarker, paramName);
}

currTokenType = TokenType.None;
Expand All @@ -705,12 +702,12 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
case TokenType.Quoted :
switch (ch)
{
case '\'':
case '\'' :
currTokenLen++;

break;

default:
default :
if (currTokenLen > 1 && lastChar == '\'')
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
Expand All @@ -734,40 +731,43 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
break;

case TokenType.Colon :
switch (ch)
if (IsParamNameChar(ch))
{
case ':':
currTokenLen++;

break;

default:
if (currTokenLen == 1)
{
currTokenType = TokenType.Param;

currTokenBeg = currCharOfs;
currTokenLen = 0;
paramMarker = ':';
}
else
{
dest.WriteString(src.Substring(currTokenBeg, currTokenLen));
// Switch to parameter name token, include this character.
currTokenType = TokenType.Param;

currTokenType = TokenType.None;
currTokenBeg = currCharOfs;
currTokenLen = 1;
paramMarker = ':';
}
else
{
// Demote to the unknown token type and continue.
currTokenType = TokenType.None;
currTokenLen++;
}

currTokenBeg = currCharOfs;
currTokenLen = 0;
}
break;

// Re-evaluate this character
goto ProcessCharacter;
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;
Expand All @@ -776,40 +776,33 @@ private void AppendCommandReplacingParameterValues(Stream dest, string src, int
switch (currTokenType)
{
case TokenType.Param :
if (currTokenLen == 0)
{
dest.WriteBytes((byte)ASCIIBytes.Colon);
}
else
{
string paramName = src.Substring(currTokenBeg, currTokenLen);
NpgsqlParameter parameter;
bool wroteParam = false;
string paramName = src.Substring(currTokenBeg, currTokenLen);
NpgsqlParameter parameter;
bool wroteParam = false;

if (parameters.TryGetValue(paramName, out parameter))
if (parameters.TryGetValue(paramName, out parameter))
{
if (
(parameter.Direction == ParameterDirection.Input) ||
(parameter.Direction == ParameterDirection.InputOutput)
)
{
if (
(parameter.Direction == ParameterDirection.Input) ||
(parameter.Direction == ParameterDirection.InputOutput)
)
if (prepare)
{
if (prepare)
{
AppendParameterPlaceHolder(dest, parameter, paramOrdinalMap[parameter]);
}
else
{
AppendParameterValue(dest, parameter);
}
AppendParameterPlaceHolder(dest, parameter, paramOrdinalMap[parameter]);
}
else
{
AppendParameterValue(dest, parameter);
}

wroteParam = true;
}

if (! wroteParam)
{
dest.WriteString("{0}{1}", paramMarker, paramName);
}
wroteParam = true;
}

if (! wroteParam)
{
dest.WriteString("{0}{1}", paramMarker, paramName);
}

break;
Expand Down
27 changes: 27 additions & 0 deletions tests/CommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3481,5 +3481,32 @@ public void DataTypeTests()
Assert.AreEqual(typeof(NpgsqlTimeTZ), result.GetType());
*/
}

[Test]
// Target NpgsqlCommand.AppendCommandReplacingParameterValues()'s handling of operator @@.
public void Operator_At_At_RewriteTest()
{
NpgsqlCommand cmd = new NpgsqlCommand("SELECT to_tsvector('fat cats ate rats') @@ to_tsquery('cat & rat')", Conn);

Assert.IsTrue((bool)cmd.ExecuteScalar());
}

[Test]
// Target NpgsqlCommand.AppendCommandReplacingParameterValues()'s handling of operator @>.
public void Operator_At_GT_RewriteTest()
{
NpgsqlCommand cmd = new NpgsqlCommand("SELECT 'cat'::tsquery @> 'cat & rat'::tsquery", Conn);

Assert.IsFalse((bool)cmd.ExecuteScalar());
}

[Test]
// Target NpgsqlCommand.AppendCommandReplacingParameterValues()'s handling of operator <@.
public void Operator_LT_At_RewriteTest()
{
NpgsqlCommand cmd = new NpgsqlCommand("SELECT 'cat'::tsquery <@ 'cat & rat'::tsquery", Conn);

Assert.IsTrue((bool)cmd.ExecuteScalar());
}
}
}