/
dev-npgsql
/
npgsql
Обзор
Документация
Войти
/
dev-npgsql
/
npgsql
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
v4.1.15
src/Npgsql/NpgsqlStatement.cs
116 строк
4 KB
Shay Rojansky
Fix race condition around preparation
12 май 2020, 12:26
12 май 2020, 12:26
94abcf1
Код
Авторство
О чём код?
using System.Collections.Generic; using Npgsql.BackendMessages; namespace Npgsql { /// <summary> /// Represents a single SQL statement within Npgsql. /// /// Instances aren't constructed directly; users should construct an <see cref="NpgsqlCommand"/> /// object and populate its <see cref="NpgsqlCommand.CommandText"/> property as in standard ADO.NET. /// Npgsql will analyze that property and constructed instances of <see cref="NpgsqlStatement"/> /// internally. /// /// Users can retrieve instances from <see cref="NpgsqlDataReader.Statements"/> /// and access information about statement execution (e.g. affected rows). /// </summary> public sealed class NpgsqlStatement { /// <summary> /// The SQL text of the statement. /// </summary> public string SQL { get; set; } = string.Empty; /// <summary> /// Specifies the type of query, e.g. SELECT. /// </summary> public StatementType StatementType { get; internal set; } /// <summary> /// The number of rows affected or retrieved. /// </summary> /// <remarks> /// See the command tag in the CommandComplete message, /// http://www.postgresql.org/docs/current/static/protocol-message-formats.html /// </remarks> public uint Rows { get; internal set; } /// <summary> /// For an INSERT, the object ID of the inserted row if <see cref="Rows"/> is 1 and /// the target table has OIDs; otherwise 0. /// </summary> public uint OID { get; internal set; } /// <summary> /// The input parameters sent with this statement. /// </summary> public List<NpgsqlParameter> InputParameters { get; } = new List<NpgsqlParameter>(); /// <summary> /// The RowDescription message for this query. If null, the query does not return rows (e.g. INSERT) /// </summary> internal RowDescriptionMessage? Description { get => PreparedStatement == null ? _description : PreparedStatement.Description; set { if (PreparedStatement == null) _description = value; else PreparedStatement.Description = value; } } RowDescriptionMessage? _description; /// <summary> /// If this statement has been automatically prepared, references the <see cref="PreparedStatement"/>. /// Null otherwise. /// </summary> internal PreparedStatement? PreparedStatement { get => _preparedStatement != null && _preparedStatement.State == PreparedState.Unprepared ? _preparedStatement = null : _preparedStatement; set => _preparedStatement = value; } PreparedStatement? _preparedStatement; internal bool IsPreparing; /// <summary> /// Holds the server-side (prepared) statement name. Empty string for non-prepared statements. /// </summary> internal string StatementName => PreparedStatement?.Name ?? ""; /// <summary> /// Whether this statement has already been prepared (including automatic preparation). /// </summary> internal bool IsPrepared => PreparedStatement?.IsPrepared == true; internal void Reset() { SQL = string.Empty; StatementType = StatementType.Select; _description = null; Rows = 0; OID = 0; InputParameters.Clear(); PreparedStatement = null; } internal void ApplyCommandComplete(CommandCompleteMessage msg) { StatementType = msg.StatementType; // Downcast to uint for backwards compat with 4.0 Rows = (uint)msg.Rows; OID = msg.OID; } /// <summary> /// Returns the SQL text of the statement. /// </summary> public override string ToString() => SQL ?? "<none>"; } }