Skip to content
Permalink
Browse files

Fix SQL query parsing

Our SQL query parser supports an ancient "non-conforming string" mode
from pre PG 9.1. Unfortunately, commit
f1bf198 introduced a bug where we
erroneously went into this mode.

Fixes #2660
  • Loading branch information...
roji committed Sep 30, 2019
1 parent 059ff87 commit 239a9192aaa1c18f985386a036ce4b06027711e8
@@ -262,7 +262,7 @@ internal NpgsqlConnector(NpgsqlConnection connection)
Settings = settings;
ConnectionString = connectionString;
PostgresParameters = new Dictionary<string, string>();
SqlParser = new SqlQueryParser(UseConformantStrings);
SqlParser = new SqlQueryParser();
Transaction = new NpgsqlTransaction(this);

CancelLock = new object();
@@ -1872,7 +1872,7 @@ async Task DoWaitAsync(CancellationToken cancellationToken)

#region Supported features and PostgreSQL settings

internal bool UseConformantStrings { get; private set; }
internal bool UseConformingStrings { get; private set; }

/// <summary>
/// The connection's timezone as reported by PostgreSQL, in the IANA/Olson database format.
@@ -1941,7 +1941,8 @@ void ReadParameterStatus(ReadOnlySpan<byte> incomingName, ReadOnlySpan<byte> inc
switch (name)
{
case "standard_conforming_strings":
UseConformantStrings = (value == "on");
UseConformingStrings = value == "on";
SqlParser.StandardConformingStrings = UseConformingStrings;
return;

case "TimeZone":
@@ -13,15 +13,12 @@ class SqlQueryParser
{
readonly Dictionary<string, int> _paramIndexMap = new Dictionary<string, int>();
readonly StringBuilder _rewrittenSql = new StringBuilder();
readonly bool _standardConformantStrings;
internal bool StandardConformingStrings { get; set; } = true;

List<NpgsqlStatement> _statements = default!;
NpgsqlStatement _statement = default!;
int _statementIndex;

internal SqlQueryParser(bool standardConformantStrings)
=> _standardConformantStrings = standardConformantStrings;

/// <summary>
/// Receives a raw SQL query as passed in by the user, and performs some processing necessary
/// before sending to the backend.
@@ -68,7 +65,7 @@ void ParseRawQuery(ReadOnlySpan<char> sql, NpgsqlParameterCollection parameters,
case '-':
goto LineCommentBegin;
case '\'':
if (_standardConformantStrings)
if (StandardConformingStrings)
goto Quoted;
else
goto Escaped;
@@ -462,6 +462,23 @@ public void Bug2296()
}
}

[Test, IssueLink("https://github.com/npgsql/npgsql/issues/2660")]
public void StandardConformingStrings()
{
using var conn = OpenConnection();

var sql = @"
SELECT table_name
FROM information_schema.views
WHERE table_name LIKE @p0 escape '\' AND (is_updatable = 'NO') = @p1";

using var cmd = new NpgsqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@p0", "%trig%");
cmd.Parameters.AddWithValue("@p1", true);
using var reader = cmd.ExecuteReader();
reader.Read();
}

#region Bug1285

[Test, IssueLink("https://github.com/npgsql/npgsql/issues/1285")]
@@ -77,9 +77,9 @@ public void ParamDoesntGetBound(string sql)
}

[Test]
public void NonConformantStrings()
public void NonConformingStrings()
{
var parser = new SqlQueryParser(false);
var parser = new SqlQueryParser() { StandardConformingStrings = false };
parser.ParseRawQuery(@"SELECT 'abc\':str''a:str'", _params, _queries);
Assert.That(_queries.Single().SQL, Is.EqualTo(@"SELECT 'abc\':str''a:str'"));
Assert.That(_queries.Single().InputParameters, Is.Empty);
@@ -184,7 +184,7 @@ public void TrimWhitespace()
[SetUp]
public void SetUp()
{
_parser = new SqlQueryParser(true);
_parser = new SqlQueryParser();
_queries = new List<NpgsqlStatement>();
_params = new NpgsqlParameterCollection();
}

0 comments on commit 239a919

Please sign in to comment.
You can’t perform that action at this time.