Skip to content

Commit c1cd8c1

Browse files
committed
NpgsqlCommand.ExecuteBlind()
ExecuteBlind() is now static, eliminating all NpgsqlCommand instantiation overhead.
1 parent d2843aa commit c1cd8c1

7 files changed

Lines changed: 80 additions & 64 deletions

Npgsql/Npgsql/NpgsqlCommand.PrepareExecute.cs

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,74 @@ namespace Npgsql
4747
public sealed partial class NpgsqlCommand : DbCommand, ICloneable
4848
{
4949
/// <summary>
50-
/// Slightly optimised version of ExecuteNonQuery() for internal use in cases where the number
50+
/// Internal query shortcut for use in cases where the number
5151
/// of affected rows is of no interest.
52-
/// This function must not be called with a query that returns result rows, after calling Prepare(), or.
53-
/// with a query that requires parameter substitution of any kind.
5452
/// </summary>
55-
internal void ExecuteBlind()
53+
internal static void ExecuteBlind(NpgsqlConnector connector, byte[] command, int timeout = 20)
5654
{
5755
NpgsqlQuery query;
5856

59-
// Bypass cpmmand parsing overhead and send commandText verbatim.
60-
query = NpgsqlQuery.Create(m_Connector.BackendProtocolVersion, commandText);
57+
connector.SetBackendCommandTimeout(timeout);
58+
59+
// Bypass cpmmand parsing overhead and send command verbatim.
60+
query = NpgsqlQuery.Create(connector.BackendProtocolVersion, command);
61+
62+
// Block the notification thread before writing anything to the wire.
63+
using (var blocker = connector.BlockNotificationThread())
64+
{
65+
// Write the Query message to the wire.
66+
connector.Query(query);
67+
68+
// Flush, and wait for and discard all responses.
69+
connector.ProcessAndDiscardBackendResponses();
70+
}
71+
}
72+
73+
/// <summary>
74+
/// Internal query shortcut for use in cases where the number
75+
/// of affected rows is of no interest.
76+
/// </summary>
77+
internal static void ExecuteBlind(NpgsqlConnector connector, string command, int timeout = 20)
78+
{
79+
NpgsqlQuery query;
80+
81+
connector.SetBackendCommandTimeout(timeout);
82+
83+
// Bypass cpmmand parsing overhead and send command verbatim.
84+
query = NpgsqlQuery.Create(connector.BackendProtocolVersion, command);
6185

6286
// Block the notification thread before writing anything to the wire.
63-
using (var blocker = m_Connector.BlockNotificationThread())
87+
using (var blocker = connector.BlockNotificationThread())
6488
{
6589
// Write the Query message to the wire.
66-
m_Connector.Query(query);
90+
connector.Query(query);
6791

6892
// Flush, and wait for and discard all responses.
69-
m_Connector.ProcessAndDiscardBackendResponses();
93+
connector.ProcessAndDiscardBackendResponses();
7094
}
7195
}
7296

97+
/// <summary>
98+
/// Special adaptation of ExecuteBlind() that sets statement_timeout.
99+
/// This exists to prevent Connector.SetBackendCommandTimeout() from calling Command.ExecuteBlind(),
100+
/// which will cause an endless recursive loop.
101+
/// </summary>
102+
/// <param name="connector"></param>
103+
/// <param name="timeout">Timeout in seconds.</param>
104+
internal static void ExecuteSetStatementTimeoutBlind(NpgsqlConnector connector, int timeout)
105+
{
106+
NpgsqlQuery query;
107+
108+
// Bypass cpmmand parsing overhead and send command verbatim.
109+
query = NpgsqlQuery.Create(connector.BackendProtocolVersion, string.Format("SET statement_timeout = {0}", timeout * 1000));
110+
111+
// Write the Query message to the wire.
112+
connector.Query(query);
113+
114+
// Flush, and wait for and discard all responses.
115+
connector.ProcessAndDiscardBackendResponses();
116+
}
117+
73118
/// <summary>
74119
/// Executes a SQL statement against the connection and returns the number of rows affected.
75120
/// </summary>
@@ -394,13 +439,8 @@ private void PrepareInternal()
394439
planName = Connector.NextPlanName();
395440
preparedCommandText = GetCommandText(true, false);
396441

397-
// BackendEncoding.UTF8Encoding.GetString() is temporary. A new optimization for
398-
// ExecuteBlind() will negate the need.
399-
using (NpgsqlCommand command = new NpgsqlCommand(BackendEncoding.UTF8Encoding.GetString(preparedCommandText), m_Connector))
400-
{
401-
command.ExecuteBlind();
402-
prepared = PrepareStatus.V2Prepared;
403-
}
442+
ExecuteBlind(m_Connector, preparedCommandText);
443+
prepared = PrepareStatus.V2Prepared;
404444

405445
// Tell to mediator what command is being sent.
406446
m_Connector.Mediator.SetSqlSent(preparedCommandText, NpgsqlMediator.SQLSentType.Prepare);

Npgsql/Npgsql/NpgsqlConnector.cs

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -430,21 +430,14 @@ internal void ReleaseResources()
430430

431431
internal void ReleaseWithDiscard()
432432
{
433-
using (NpgsqlCommand cmd = new NpgsqlCommand("DISCARD ALL", this, 60))
434-
{
435-
cmd.ExecuteBlind();
436-
}
433+
NpgsqlCommand.ExecuteBlind(this, "DISCARD ALL", 60);
437434

438435
// The initial connection parameters will be restored via IsValid() when get connector from pool later
439436
}
440437

441438
internal void ReleaseRegisteredListen()
442439
{
443-
//Query(new NpgsqlCommand("unlisten *", this));
444-
using(NpgsqlCommand cmd = new NpgsqlCommand("unlisten *", this))
445-
{
446-
cmd.ExecuteBlind();
447-
}
440+
NpgsqlCommand.ExecuteBlind(this, "UNLISTEN *");
448441
}
449442

450443
/// <summary>
@@ -460,15 +453,10 @@ internal void ReleasePlansPortals()
460453
{
461454
try
462455
{
463-
//Query(new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i), this));
464-
using(NpgsqlCommand cmd = new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i.ToString()), this))
465-
{
466-
cmd.ExecuteBlind();
467-
}
456+
NpgsqlCommand.ExecuteBlind(this, String.Format("DEALLOCATE \"{0}{1}\";", _planNamePrefix, i), -1);
468457
}
469-
470458
// Ignore any error which may occur when releasing portals as this portal name may not be valid anymore. i.e.: the portal name was used on a prepared query which had errors.
471-
catch(Exception) {}
459+
catch {}
472460
}
473461
}
474462

@@ -484,9 +472,7 @@ internal void SetBackendCommandTimeout(int timeout)
484472
{
485473
if (Mediator.BackendCommandTimeout == -1 || Mediator.BackendCommandTimeout != timeout)
486474
{
487-
NpgsqlCommand toq = new NpgsqlCommand(string.Format("SET statement_timeout = {0}", timeout * 1000), this);
488-
489-
toq.ExecuteBlind();
475+
NpgsqlCommand.ExecuteSetStatementTimeoutBlind(this, timeout);
490476

491477
Mediator.BackendCommandTimeout = timeout;
492478
}
@@ -984,8 +970,7 @@ internal void Open()
984970

985971
initQueries = sbInitQueries.ToString();
986972

987-
NpgsqlCommand initCommand = new NpgsqlCommand(initQueries, this, 60);
988-
initCommand.ExecuteBlind();
973+
NpgsqlCommand.ExecuteBlind(this, initQueries, 60);
989974

990975
// Make a shallow copy of the type mapping that the connector will own.
991976
// It is possible that the connector may add types to its private

Npgsql/Npgsql/NpgsqlCopyIn.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public void Start()
140140
if (_context.CurrentState is NpgsqlReadyState)
141141
{
142142
_context.Mediator.CopyStream = _copyStream;
143-
_cmd.ExecuteBlind();
143+
_cmd.ExecuteNonQuery();
144144
_disposeCopyStream = _copyStream == null;
145145
_copyStream = _context.Mediator.CopyStream;
146146
if (_copyStream == null && ! (_context.CurrentState is NpgsqlReadyState))

Npgsql/Npgsql/NpgsqlCopyOut.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public void Start()
130130
if (_context.CurrentState is NpgsqlReadyState)
131131
{
132132
_context.Mediator.CopyStream = _copyStream;
133-
_cmd.ExecuteBlind();
133+
_cmd.ExecuteNonQuery();
134134
_disposeCopyStream = _copyStream == null;
135135
_copyStream = _context.Mediator.CopyStream;
136136
if (_copyStream == null && ! (_context.CurrentState is NpgsqlReadyState))

Npgsql/Npgsql/NpgsqlState.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,8 @@ public void TestNotify(NpgsqlConnector context)
111111
throw new EndOfStreamException();
112112
case 'Z':
113113
//context.Query(new NpgsqlCommand("UNLISTEN *", context));
114-
using(NpgsqlCommand cmd = new NpgsqlCommand("UNLISTEN *", context))
115-
{
116-
cmd.ExecuteBlind();
117-
}
114+
NpgsqlCommand.ExecuteBlind(context, "UNLISTEN *");
115+
118116
return;
119117
}
120118
}

Npgsql/Npgsql/NpgsqlTransaction.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
8080

8181
commandText.Append(";");
8282

83-
NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector);
84-
command.ExecuteBlind();
83+
NpgsqlCommand.ExecuteBlind(conn.Connector, commandText.ToString());
84+
8585
_conn.Connector.Transaction = this;
8686
}
8787

@@ -160,8 +160,8 @@ public override void Commit()
160160

161161
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Commit");
162162

163-
NpgsqlCommand command = new NpgsqlCommand("COMMIT", _conn.Connector);
164-
command.ExecuteBlind();
163+
NpgsqlCommand.ExecuteBlind(_conn.Connector, "COMMIT");
164+
165165
_conn.Connector.Transaction = null;
166166
_conn = null;
167167
}
@@ -180,8 +180,7 @@ public override void Rollback()
180180

181181
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Rollback");
182182

183-
NpgsqlCommand command = new NpgsqlCommand("ROLLBACK", _conn.Connector);
184-
command.ExecuteBlind();
183+
NpgsqlCommand.ExecuteBlind(_conn.Connector, "ROLLBACK");
185184
_conn.Connector.Transaction = null;
186185
_conn = null;
187186
}
@@ -210,9 +209,7 @@ public void Rollback(String savePointName)
210209

211210
}
212211

213-
NpgsqlCommand command = new NpgsqlCommand("ROLLBACK TO SAVEPOINT " + savePointName, _conn.Connector);
214-
command.ExecuteBlind();
215-
212+
NpgsqlCommand.ExecuteBlind(_conn.Connector, string.Format("ROLLBACK TO SAVEPOINT {0}", savePointName));
216213
}
217214

218215
/// <summary>
@@ -240,8 +237,7 @@ public void Save(String savePointName)
240237

241238
}
242239

243-
NpgsqlCommand command = new NpgsqlCommand("SAVEPOINT " + savePointName, _conn.Connector);
244-
command.ExecuteBlind();
240+
NpgsqlCommand.ExecuteBlind(_conn.Connector, string.Format("SAVEPOINT {0}", savePointName));
245241

246242
}
247243
/// <summary>

Npgsql/Npgsql/NpgsqlTransactionCallbacks.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,15 @@ public void CommitTransaction()
8787
{
8888
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "CommitTransaction");
8989
NpgsqlConnection connection = GetConnection();
90-
NpgsqlCommand command = null;
90+
9191
if (_prepared)
9292
{
93-
command = new NpgsqlCommand(string.Format("COMMIT PREPARED '{0}'", _txName), connection);
93+
NpgsqlCommand.ExecuteBlind(connection.Connector, string.Format("COMMIT PREPARED '{0}'", _txName));
9494
}
9595
else
9696
{
97-
command = new NpgsqlCommand("COMMIT", connection);
97+
NpgsqlCommand.ExecuteBlind(connection.Connector, "COMMIT");
9898
}
99-
command.ExecuteBlind();
10099
}
101100

102101
public void PrepareTransaction()
@@ -105,8 +104,7 @@ public void PrepareTransaction()
105104
{
106105
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "PrepareTransaction");
107106
NpgsqlConnection connection = GetConnection();
108-
NpgsqlCommand command = new NpgsqlCommand(string.Format("PREPARE TRANSACTION '{0}'", _txName), connection);
109-
command.ExecuteBlind();
107+
NpgsqlCommand.ExecuteBlind(connection.Connector, string.Format("PREPARE TRANSACTION '{0}'", _txName));
110108
_prepared = true;
111109
}
112110
}
@@ -115,16 +113,15 @@ public void RollbackTransaction()
115113
{
116114
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "RollbackTransaction");
117115
NpgsqlConnection connection = GetConnection();
118-
NpgsqlCommand command = null;
116+
119117
if (_prepared)
120118
{
121-
command = new NpgsqlCommand(string.Format("ROLLBACK PREPARED '{0}'", _txName), connection);
119+
NpgsqlCommand.ExecuteBlind(connection.Connector, string.Format("ROLLBACK PREPARED '{0}'", _txName));
122120
}
123121
else
124122
{
125-
command = new NpgsqlCommand("ROLLBACK", connection);
123+
NpgsqlCommand.ExecuteBlind(connection.Connector, "ROLLBACK");
126124
}
127-
command.ExecuteBlind();
128125
}
129126

130127
#endregion

0 commit comments

Comments
 (0)