Permalink
Browse files

Merge branch 'hotfix/3.2.6'

  • Loading branch information...
roji committed Dec 3, 2017
2 parents 720fead + 5da57f0 commit 7a8bc2381e109d35760a319964460c5f3c79c64a
View
@@ -1,5 +1,5 @@
image: Visual Studio 2017 Preview
version: 3.2.5-{build}
version: 3.2.6-{build}
environment:
global:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
View
@@ -2,7 +2,7 @@ language: csharp
dist: trusty
sudo: false
mono: none
dotnet: 2.0.0-preview1-005977
dotnet: 2.0.3
services:
- postgresql
@@ -26,11 +26,13 @@
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Npgsql.BackendMessages;
namespace Npgsql.FrontendMessages
{
class PasswordMessage : SimpleFrontendMessage
class PasswordMessage : FrontendMessage
{
internal byte[] Payload { get; private set; }
internal int PayloadOffset { get; private set; }
@@ -107,13 +109,22 @@ internal PasswordMessage Populate(byte[] payload, int offset, int count)
return this;
}
internal override int Length => 1 + 4 + PayloadLength;
internal override void WriteFully(WriteBuffer buf)
internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
{
if (buf.WriteSpaceLeft < 1 + 5)
await buf.Flush(async);
buf.WriteByte(Code);
buf.WriteInt32(Length - 1);
buf.WriteBytes(Payload, PayloadOffset, Payload.Length);
buf.WriteInt32(4 + PayloadLength);
if (PayloadLength <= buf.WriteSpaceLeft)
{
// The entire array fits in our buffer, copy it into the buffer as usual.
buf.WriteBytes(Payload, PayloadOffset, Payload.Length);
return;
}
await buf.Flush(async);
buf.DirectWrite(Payload, PayloadOffset, PayloadLength);
}
public override string ToString() => "[Password]";
View
@@ -6,7 +6,7 @@
<Copyright>Copyright 2017 © The Npgsql Development Team</Copyright>
<Company>Npgsql</Company>
<PackageTags>npgsql postgresql postgres ado ado.net database sql</PackageTags>
<VersionPrefix>3.2.5</VersionPrefix>
<VersionPrefix>3.2.6</VersionPrefix>
<TargetFrameworks>net45;net451;netstandard1.3;netstandard2.0</TargetFrameworks>
<WarningsAsErrors>true</WarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@@ -16,7 +16,7 @@
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageProjectUrl>http://www.npgsql.org</PackageProjectUrl>
<PackageIconUrl>http://www.npgsql.org/img/postgresql.gif</PackageIconUrl>
<PackageLicenseUrl>https://raw.githubusercontent.com/npgsql/npgsql/develop/LICENSE.txt</PackageLicenseUrl>
<PackageLicenseUrl>https://raw.githubusercontent.com/npgsql/npgsql/master/LICENSE.txt</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>git://github.com/npgsql/npgsql</RepositoryUrl>
<!-- This is somehow important for Microsoft.ApiDesignGuidelines.Analyzers -->
@@ -29,7 +29,9 @@
<ItemGroup>
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.3.0" />
<!--
<PackageReference Include="Microsoft.ApiDesignGuidelines.Analyzers" Version="1.2.0-beta2" PrivateAssets="All" />
-->
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
@@ -72,11 +72,24 @@ internal NpgsqlBinaryExporter(NpgsqlConnector connector, string copyToCommand)
{
_connector.SendQuery(copyToCommand);
// TODO: Failure will break the connection (e.g. if we get CopyOutResponse), handle more gracefully
var copyOutResponse = _connector.ReadExpecting<CopyOutResponseMessage>();
if (!copyOutResponse.IsBinary) {
throw new ArgumentException("copyToCommand triggered a text transfer, only binary is allowed", nameof(copyToCommand));
CopyOutResponseMessage copyOutResponse;
var msg = _connector.ReadMessage();
switch (msg.Code)
{
case BackendMessageCode.CopyOutResponse:
copyOutResponse = (CopyOutResponseMessage)msg;
if (!copyOutResponse.IsBinary)
throw new ArgumentException("copyToCommand triggered a text transfer, only binary is allowed", nameof(copyToCommand));
break;
case BackendMessageCode.CompletedResponse:
throw new InvalidOperationException(
"This API only supports import/export from the client, i.e. COPY commands containing TO/FROM STDIN. " +
"To import/export with files on your PostgreSQL machine, simply execute the command with ExecuteNonQuery. " +
"Note that your data has been successfully imported/exported.");
default:
throw _connector.UnexpectedMessageReceived(msg.Code);
}
NumColumns = copyOutResponse.NumColumns;
ReadHeader();
}
@@ -89,10 +89,24 @@ internal NpgsqlBinaryImporter(NpgsqlConnector connector, string copyFromCommand)
{
_connector.SendQuery(copyFromCommand);
// TODO: Failure will break the connection (e.g. if we get CopyOutResponse), handle more gracefully
var copyInResponse = _connector.ReadExpecting<CopyInResponseMessage>();
if (!copyInResponse.IsBinary)
throw new ArgumentException("copyFromCommand triggered a text transfer, only binary is allowed", nameof(copyFromCommand));
CopyInResponseMessage copyInResponse;
var msg = _connector.ReadMessage();
switch (msg.Code)
{
case BackendMessageCode.CopyInResponse:
copyInResponse = (CopyInResponseMessage)msg;
if (!copyInResponse.IsBinary)
throw new ArgumentException("copyFromCommand triggered a text transfer, only binary is allowed", nameof(copyFromCommand));
break;
case BackendMessageCode.CompletedResponse:
throw new InvalidOperationException(
"This API only supports import/export from the client, i.e. COPY commands containing TO/FROM STDIN. " +
"To import/export with files on your PostgreSQL machine, simply execute the command with ExecuteNonQuery. " +
"Note that your data has been successfully imported/exported.");
default:
throw _connector.UnexpectedMessageReceived(msg.Code);
}
NumColumns = copyInResponse.NumColumns;
_buf.StartCopyMode();
WriteHeader();
@@ -328,7 +328,8 @@ public override string ConnectionString
/// </summary>
/// <value>The name of the current database or the name of the database to be
/// used after a connection is opened. The default value is the empty string.</value>
public override string Database => Settings.Database;
[CanBeNull]
public override string Database => Settings.Database ?? Settings.Username;
/// <summary>
/// Gets the string identifying the database server (host and port)
@@ -69,6 +69,9 @@ sealed partial class NpgsqlConnector : IDisposable
internal NpgsqlConnectionStringBuilder Settings { get; }
internal string ConnectionString { get; }
[CanBeNull] ProvideClientCertificatesCallback ProvideClientCertificatesCallback { get; }
[CanBeNull] RemoteCertificateValidationCallback UserCertificateValidationCallback { get; }
internal Encoding TextEncoding { get; private set; }
/// <summary>
@@ -263,6 +266,15 @@ internal NpgsqlConnector(NpgsqlConnection connection)
{
Connection = connection;
Connection.Connector = this;
ProvideClientCertificatesCallback = Connection.ProvideClientCertificatesCallback;
UserCertificateValidationCallback = Connection.UserCertificateValidationCallback;
}
NpgsqlConnector(NpgsqlConnector connector)
: this(connector.Settings, connector.ConnectionString)
{
ProvideClientCertificatesCallback = connector.ProvideClientCertificatesCallback;
UserCertificateValidationCallback = connector.UserCertificateValidationCallback;
}
/// <summary>
@@ -537,13 +549,13 @@ async Task RawOpen(NpgsqlTimeout timeout, bool async, CancellationToken cancella
break;
case 'S':
var clientCertificates = new X509CertificateCollection();
Connection.ProvideClientCertificatesCallback?.Invoke(clientCertificates);
ProvideClientCertificatesCallback?.Invoke(clientCertificates);
RemoteCertificateValidationCallback certificateValidationCallback;
if (Settings.TrustServerCertificate)
certificateValidationCallback = (sender, certificate, chain, errors) => true;
else if (Connection.UserCertificateValidationCallback != null)
certificateValidationCallback = Connection.UserCertificateValidationCallback;
else if (UserCertificateValidationCallback != null)
certificateValidationCallback = UserCertificateValidationCallback;
else
certificateValidationCallback = DefaultUserCertificateValidationCallback;
@@ -569,6 +581,7 @@ async Task RawOpen(NpgsqlTimeout timeout, bool async, CancellationToken cancella
_stream = sslStream;
}
timeout.Check();
ReadBuffer.Clear(); // Reset to empty after reading single SSL char
ReadBuffer.Underlying = _stream;
WriteBuffer.Underlying = _stream;
IsSecure = true;
@@ -1225,8 +1238,8 @@ internal void CancelRequest()
{
try
{
var cancelConnector = new NpgsqlConnector(Settings, ConnectionString);
cancelConnector.DoCancelRequest(BackendProcessId, _backendSecretKey, cancelConnector.ConnectionTimeout);
var cancelConnector = new NpgsqlConnector(this);
cancelConnector.DoCancelRequest(BackendProcessId, _backendSecretKey);
}
catch (Exception e)
{
@@ -1237,13 +1250,13 @@ internal void CancelRequest()
}
}
void DoCancelRequest(int backendProcessId, int backendSecretKey, int connectionTimeout)
void DoCancelRequest(int backendProcessId, int backendSecretKey)
{
Debug.Assert(State == ConnectorState.Closed);
try
{
RawOpen(new NpgsqlTimeout(TimeSpan.FromSeconds(connectionTimeout)), false, CancellationToken.None)
RawOpen(new NpgsqlTimeout(TimeSpan.FromSeconds(ConnectionTimeout)), false, CancellationToken.None)
.GetAwaiter().GetResult();
SendMessage(new CancelRequestMessage(backendProcessId, backendSecretKey));
@@ -271,6 +271,8 @@ ReadResult ProcessMessage(IBackendMessage msg)
goto case BackendMessageCode.EmptyQueryResponse;
case BackendMessageCode.EmptyQueryResponse:
if (!_hasRows.HasValue)
_hasRows = false;
_state = ReaderState.BetweenResults;
return ReadResult.RowNotRead;
@@ -305,7 +307,7 @@ public sealed override bool NextResult()
catch (PostgresException e)
{
_state = ReaderState.Consumed;
if ((_statementIndex >= 0) && (_statementIndex < _statements.Count))
if (_statementIndex >= 0 && _statementIndex < _statements.Count)
e.Statement = _statements[_statementIndex];
throw;
}
@@ -333,7 +335,7 @@ public override Task<bool> NextResultAsync(CancellationToken cancellationToken)
}
});
async Task<bool> NextResult(bool async)
async Task<bool> NextResult(bool async, bool isConsuming = false)
{
Debug.Assert(!IsSchemaOnly);
@@ -364,10 +366,9 @@ async Task<bool> NextResult(bool async)
Debug.Assert(_state == ReaderState.BetweenResults);
_hasRows = null;
if ((_behavior & CommandBehavior.SingleResult) != 0 && _statementIndex == 0)
if ((_behavior & CommandBehavior.SingleResult) != 0 && _statementIndex == 0 && !isConsuming)
{
if (_state == ReaderState.BetweenResults)
await Consume(async);
await Consume(async);
return false;
}
@@ -641,34 +642,12 @@ public override string GetName(int ordinal)
/// </summary>
async Task Consume(bool async)
{
if (IsSchemaOnly && _statements.All(s => s.IsPrepared))
{
_state = ReaderState.Consumed;
return;
}
if (_row != null)
{
await _row.Consume(async);
_row = null;
}
// Skip over the other result sets, processing only CommandCompleted for RecordsAffected
while (true)
{
var msg = await SkipUntil(BackendMessageCode.CompletedResponse, BackendMessageCode.ReadyForQuery, async);
switch (msg.Code)
{
case BackendMessageCode.CompletedResponse:
ProcessMessage(msg);
continue;
case BackendMessageCode.ReadyForQuery:
ProcessMessage(msg);
return;
default:
throw new NpgsqlException("Unexpected message of type " + msg.Code);
}
}
// Skip over the other result sets. Note that this does tally records affected
// from CommandComplete messages, and properly sets state for auto-prepared statements
if (IsSchemaOnly)
while (await NextResultSchemaOnly(async)) {}
else
while (await NextResult(async, true)) {}
}
/// <summary>
@@ -1422,17 +1401,23 @@ public override DataTable GetSchemaTable()
var table = new DataTable("SchemaTable");
table.Columns.Add("AllowDBNull", typeof(bool));
table.Columns.Add("BaseCatalogName", typeof(string));
table.Columns.Add("BaseColumnName", typeof(string));
table.Columns.Add("BaseSchemaName", typeof(string));
table.Columns.Add("BaseTableName", typeof(string));
// Note: column order is important to match SqlClient's, some ADO.NET users appear
// to assume ordering (see #1671)
table.Columns.Add("ColumnName", typeof(string));
table.Columns.Add("ColumnOrdinal", typeof(int));
table.Columns.Add("ColumnSize", typeof(int));
table.Columns.Add("DataType", typeof(Type));
table.Columns.Add("NumericPrecision", typeof(int));
table.Columns.Add("NumericScale", typeof(int));
table.Columns.Add("IsUnique", typeof(bool));
table.Columns.Add("IsKey", typeof(bool));
table.Columns.Add("BaseServerName", typeof(string));
table.Columns.Add("BaseCatalogName", typeof(string));
table.Columns.Add("BaseColumnName", typeof(string));
table.Columns.Add("BaseSchemaName", typeof(string));
table.Columns.Add("BaseTableName", typeof(string));
table.Columns.Add("DataType", typeof(Type));
table.Columns.Add("AllowDBNull", typeof(bool));
table.Columns.Add("ProviderType", typeof(Type));
table.Columns.Add("IsAliased", typeof(bool));
table.Columns.Add("IsExpression", typeof(bool));
table.Columns.Add("IsIdentity", typeof(bool));
@@ -1441,35 +1426,35 @@ public override DataTable GetSchemaTable()
table.Columns.Add("IsHidden", typeof(bool));
table.Columns.Add("IsLong", typeof(bool));
table.Columns.Add("IsReadOnly", typeof(bool));
table.Columns.Add("NumericPrecision", typeof(int));
table.Columns.Add("NumericScale", typeof(int));
table.Columns.Add("ProviderSpecificDataType", typeof(Type));
table.Columns.Add("ProviderType", typeof(Type));
table.Columns.Add("DataTypeName", typeof(string));
foreach (var column in GetColumnSchema())
{
var row = table.NewRow();
row["AllowDBNull"] = (object)column.AllowDBNull ?? DBNull.Value;
row["BaseColumnName"] = column.BaseColumnName;
row["BaseCatalogName"] = column.BaseCatalogName;
row["BaseSchemaName"] = column.BaseSchemaName;
row["BaseTableName"] = column.BaseTableName;
row["ColumnName"] = column.ColumnName;
row["ColumnOrdinal"] = column.ColumnOrdinal ?? -1;
row["ColumnSize"] = column.ColumnSize ?? -1;
row["DataType"] = row["ProviderType"] = column.DataType; // Non-standard
row["NumericPrecision"] = column.NumericPrecision ?? 0;
row["NumericScale"] = column.NumericScale ?? 0;
row["IsUnique"] = column.IsUnique == true;
row["IsKey"] = column.IsKey == true;
row["BaseServerName"] = "";
row["BaseCatalogName"] = column.BaseCatalogName;
row["BaseColumnName"] = column.BaseColumnName;
row["BaseSchemaName"] = column.BaseSchemaName;
row["BaseTableName"] = column.BaseTableName;
row["DataType"] = row["ProviderType"] = column.DataType; // Non-standard
row["AllowDBNull"] = (object)column.AllowDBNull ?? DBNull.Value;
row["IsAliased"] = column.IsAliased == true;
row["IsExpression"] = column.IsExpression == true;
row["IsAutoIncrement"] = column.IsAutoIncrement == true;
row["IsIdentity"] = column.IsIdentity == true;
row["IsAutoIncrement"] = column.IsAutoIncrement == true;
row["IsRowVersion"] = false;
row["IsHidden"] = column.IsHidden == true;
row["IsLong"] = column.IsLong == true;
row["NumericPrecision"] = column.NumericPrecision ?? 0;
row["NumericScale"] = column.NumericScale ?? 0;
row["DataTypeName"] = column.DataTypeName;
table.Rows.Add(row);
}
Oops, something went wrong.

0 comments on commit 7a8bc23

Please sign in to comment.