Skip to content

Commit 657c1b1

Browse files
authored
Merge pull request #445 from DataObjects-NET/master-pgsql-ex-handle
Server-side exception handled as TimeoutException
2 parents 8e71c02 + 2addf58 commit 657c1b1

File tree

4 files changed

+60
-7
lines changed

4 files changed

+60
-7
lines changed

ChangeLog/7.2.0-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[postgresql] Server-side statement timeout handled as TimeoutException

Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/Driver.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ private SqlExceptionType ProcessServerSideException(PostgresException serverSide
8282
return SqlExceptionType.Deadlock;
8383
case "40001": // serialization_failure
8484
return SqlExceptionType.SerializationFailure;
85+
case "57014": {
86+
// operation timeout due to statement_timeout setting of postgres (global or per session)
87+
if (serverSideException.Message.Contains("statement timeout", StringComparison.OrdinalIgnoreCase))
88+
return SqlExceptionType.OperationTimeout;
89+
return SqlExceptionType.Unknown;
90+
}
8591
}
8692

8793
return SqlExceptionType.Unknown;

Orm/Xtensive.Orm.Tests.Sql/ExceptionTypesTest.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ private class EvilThreadArgument
3131
private const string UniqueTableName = "TheUnique";
3232
private const string CheckedTableName = "TheChecked";
3333

34-
private Schema schema;
34+
protected Schema schema;
3535

3636
protected override void TestFixtureSetUp()
3737
{
@@ -282,12 +282,12 @@ protected virtual void AssertExceptionType(SqlExceptionType expected, SqlExcepti
282282
Assert.AreEqual(expected, actual);
283283
}
284284

285-
private void AssertExceptionType(ISqlCompileUnit statement, SqlExceptionType expectedExceptionType)
285+
protected void AssertExceptionType(ISqlCompileUnit statement, SqlExceptionType expectedExceptionType)
286286
{
287287
AssertExceptionType(Connection, statement, expectedExceptionType);
288288
}
289289

290-
private void AssertExceptionType(SqlConnection connection, ISqlCompileUnit statement, SqlExceptionType expectedExceptionType)
290+
protected void AssertExceptionType(SqlConnection connection, ISqlCompileUnit statement, SqlExceptionType expectedExceptionType)
291291
{
292292
var commandText = Driver.Compile(statement).GetCommandText();
293293
AssertExceptionType(connection, commandText, expectedExceptionType);
@@ -305,7 +305,7 @@ private void AssertExceptionType(SqlConnection connection, string commandText, S
305305
Assert.Fail("Exception was not thrown");
306306
}
307307

308-
private TableColumn CreatePrimaryKey(Table table)
308+
protected TableColumn CreatePrimaryKey(Table table)
309309
{
310310
var column = table.CreateColumn(IdColumnName, Driver.TypeMappings[typeof (int)].MapType());
311311
_ = table.CreatePrimaryKey("pk_" + table.Name, column);
Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,65 @@
1-
// Copyright (C) 2010 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2010-2025 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
55
// Created: 2010.02.08
66

7+
using System.Data;
78
using NUnit.Framework;
9+
using Xtensive.Sql;
810

911
namespace Xtensive.Orm.Tests.Sql.PostgreSql
1012
{
1113
[TestFixture]
1214
public class ExceptionTypesTest : Sql.ExceptionTypesTest
1315
{
16+
private const string PgTimeoutTableName = "PgTheTimeout";
17+
private const string IdColumnName = "id";
18+
1419
protected override void CheckRequirements()
1520
{
1621
Require.ProviderIs(StorageProvider.PostgreSql);
1722
}
23+
24+
protected override void TestFixtureSetUp()
25+
{
26+
base.TestFixtureSetUp();
27+
Connection.BeginTransaction();
28+
EnsureTableNotExists(schema, PgTimeoutTableName);
29+
Connection.Commit();
30+
}
31+
32+
[Test]
33+
public void PostgreSqlServerSideTimeout()
34+
{
35+
Connection.BeginTransaction();
36+
var table = schema.CreateTable(PgTimeoutTableName);
37+
_ = CreatePrimaryKey(table);
38+
_ = ExecuteNonQuery(SqlDdl.Create(table));
39+
Connection.Commit();
40+
41+
var tableRef = SqlDml.TableRef(table);
42+
var insert = SqlDml.Insert(tableRef);
43+
insert.AddValueRow((tableRef[IdColumnName], 1));
44+
45+
using (var connectionOne = Driver.CreateConnection()) {
46+
connectionOne.Open();
47+
connectionOne.BeginTransaction();
48+
using (var command = connectionOne.CreateCommand()) {
49+
command.CommandText = "SET statement_timeout = 15";
50+
_ = command.ExecuteNonQuery();
51+
}
52+
53+
using (var connectionTwo = Driver.CreateConnection()) {
54+
connectionTwo.Open();
55+
connectionTwo.BeginTransaction(IsolationLevel.ReadCommitted);
56+
57+
using (var command = connectionTwo.CreateCommand(insert)) {
58+
_ = command.ExecuteNonQuery();
59+
}
60+
AssertExceptionType(connectionOne, insert, SqlExceptionType.OperationTimeout);
61+
}
62+
}
63+
}
1864
}
1965
}

0 commit comments

Comments
 (0)