Skip to content

Commit a9311a0

Browse files
committed
Merge remote-tracking branch 'upstream/master' into DatabaseInfo
2 parents 3f1e72c + f00a9a9 commit a9311a0

File tree

16 files changed

+277
-194
lines changed

16 files changed

+277
-194
lines changed

src/EntityFramework.Firebird/EntityFramework.Firebird.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<PackageId>EntityFramework.Firebird</PackageId>
1818
<Title>Firebird Entity Framework Provider</Title>
1919
<PackageDescription>The Entity Framework provider for Firebird enables you to develop .NET applications that connect to the Firebird database using Entity Framework.</PackageDescription>
20-
<PackageTags>firebird;firebirsql;firebirdclient;entityframewor;adonet;database</PackageTags>
20+
<PackageTags>firebird firebirsql firebirdclient entityframewor adonet database</PackageTags>
2121
</PropertyGroup>
2222
<PropertyGroup Condition="'$(Configuration)'=='Release'">
2323
<DefineConstants>EF6;TRACE</DefineConstants>

src/FirebirdSql.Data.FirebirdClient.Tests/FbZonedDateTimeTypeTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ public void EqualityFalse(FbZonedDateTime expected, FbZonedDateTime actual)
4747
Assert.AreNotEqual(expected, actual);
4848
}
4949

50+
[Test]
51+
public void ConvertToDateTimeShouldNotThrow()
52+
{
53+
var fbZonedDateTime = new FbZonedDateTime(new DateTime(2020, 12, 4, 10, 38, 0, DateTimeKind.Utc), "UTC");
54+
55+
Assert.DoesNotThrow(() => Convert.ChangeType(fbZonedDateTime, typeof(DateTime)));
56+
}
57+
5058
public void DateTimeShouldBeUtc()
5159
{
5260
Assert.Throws<ArgumentException>(() =>

src/FirebirdSql.Data.FirebirdClient.Tests/FbZonedTimeTypeTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,12 @@ public void EqualityFalse(FbZonedTime expected, FbZonedTime actual)
4646
{
4747
Assert.AreNotEqual(expected, actual);
4848
}
49+
50+
[Test]
51+
public void ConvertToTimeSpanShouldNotThrow()
52+
{
53+
var fbZonedTime = new FbZonedTime(TimeSpan.FromMinutes(142), "UTC");
54+
55+
Assert.DoesNotThrow(() => Convert.ChangeType(fbZonedTime, typeof(TimeSpan)));
56+
}
4957
}

src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public static IFbClient Create(string dllName)
8383
{
8484
result = BuildFbClient(dllName);
8585
cache.Add(dllName, result);
86-
ShutdownHelper.RegisterFbClientShutdown(() => NativeHelpers.CallIfExists(() => result.fb_shutdown(0, 0)));
86+
ShutdownHelper.RegisterFbClientShutdown(() => NativeHelpers.CallIfExists(nameof(IFbClient.fb_shutdown), () => result.fb_shutdown(0, 0)));
8787
return result;
8888
}
8989
finally

src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,13 @@ public override void Execute(int timeout, IDescriptorFiller descriptorFiller)
371371
descriptorFiller.Fill(_parameters, 0);
372372

373373
ClearStatusVector();
374-
NativeHelpers.CallIfExists(() =>
375-
{
376-
_database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout);
377-
_database.ProcessStatusVector(_statusVector);
378-
});
374+
NativeHelpers.CallIfExists(
375+
nameof(IFbClient.fb_dsql_set_timeout),
376+
() =>
377+
{
378+
_database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout);
379+
_database.ProcessStatusVector(_statusVector);
380+
});
379381

380382
ClearStatusVector();
381383

@@ -441,11 +443,13 @@ public override async ValueTask ExecuteAsync(int timeout, IDescriptorFiller desc
441443
await descriptorFiller.FillAsync(_parameters, 0, cancellationToken).ConfigureAwait(false);
442444

443445
ClearStatusVector();
444-
NativeHelpers.CallIfExists(() =>
445-
{
446-
_database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout);
447-
_database.ProcessStatusVector(_statusVector);
448-
});
446+
NativeHelpers.CallIfExists(
447+
nameof(IFbClient.fb_dsql_set_timeout),
448+
() =>
449+
{
450+
_database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout);
451+
_database.ProcessStatusVector(_statusVector);
452+
});
449453

450454
ClearStatusVector();
451455

src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,31 @@
1616
//$Authors = Jiri Cincura ([email protected])
1717

1818
using System;
19+
using System.Collections.Concurrent;
1920

2021
namespace FirebirdSql.Data.Common;
2122

2223
internal static class NativeHelpers
2324
{
24-
public static void CallIfExists(Action action)
25+
private static readonly ConcurrentDictionary<string, bool> _cache = new ConcurrentDictionary<string, bool>(StringComparer.Ordinal);
26+
27+
public static void CallIfExists(string actionId, Action action)
2528
{
26-
try
29+
if (!_cache.TryGetValue(actionId, out var executionAllowed))
30+
{
31+
try
32+
{
33+
action();
34+
_cache.TryAdd(actionId, true);
35+
}
36+
catch (EntryPointNotFoundException)
37+
{
38+
_cache.TryAdd(actionId, false);
39+
}
40+
}
41+
else if (executionAllowed)
2742
{
2843
action();
2944
}
30-
catch (EntryPointNotFoundException)
31-
{ }
3245
}
3346
}

src/FirebirdSql.Data.FirebirdClient/FirebirdSql.Data.FirebirdClient.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<PackageId>FirebirdSql.Data.FirebirdClient</PackageId>
1919
<Title>Firebird ADO.NET Data provider</Title>
2020
<PackageDescription>Firebird ADO.NET data provider</PackageDescription>
21-
<PackageTags>firebird;firebirsql;firebirdclient;adonet;database</PackageTags>
21+
<PackageTags>firebird firebirsql firebirdclient adonet database</PackageTags>
2222
<PackageReadmeFile>README.md</PackageReadmeFile>
2323
</PropertyGroup>
2424
<PropertyGroup Condition="'$(Configuration)'=='Release'">

src/FirebirdSql.Data.FirebirdClient/Services/FbBackup.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ public sealed class FbBackup : FbService
3232
public int Factor { get; set; }
3333
public string SkipData { get; set; }
3434
public FbBackupFlags Options { get; set; }
35-
public bool IncludeStatistics { get; set; } = true;
36-
public FbBackupRestoreStatistics Statistics { get; set; }
35+
public FbBackupRestoreStatistics? Statistics { get; set; }
3736

3837
public FbBackup(string connectionString = null)
3938
: base(connectionString)
@@ -68,8 +67,8 @@ public void Execute()
6867
if (!string.IsNullOrEmpty(SkipData))
6968
startSpb.Append2(IscCodes.isc_spb_bkp_skip_data, SkipData);
7069
startSpb.Append(IscCodes.isc_spb_options, (int)Options);
71-
if (IncludeStatistics)
72-
startSpb.Append2(IscCodes.isc_spb_bkp_stat, Statistics.BuildConfiguration());
70+
if (Statistics.HasValue)
71+
startSpb.Append2(IscCodes.isc_spb_bkp_stat, Statistics.Value.BuildConfiguration());
7372
if (ConnectionStringOptions.ParallelWorkers > 0)
7473
startSpb.Append(IscCodes.isc_spb_bkp_parallel_workers, ConnectionStringOptions.ParallelWorkers);
7574
StartTask(startSpb);
@@ -115,8 +114,8 @@ public async Task ExecuteAsync(CancellationToken cancellationToken = default)
115114
if (!string.IsNullOrEmpty(SkipData))
116115
startSpb.Append2(IscCodes.isc_spb_bkp_skip_data, SkipData);
117116
startSpb.Append(IscCodes.isc_spb_options, (int)Options);
118-
if (IncludeStatistics)
119-
startSpb.Append2(IscCodes.isc_spb_bkp_stat, Statistics.BuildConfiguration());
117+
if (Statistics.HasValue)
118+
startSpb.Append2(IscCodes.isc_spb_bkp_stat, Statistics.Value.BuildConfiguration());
120119
if (ConnectionStringOptions.ParallelWorkers > 0)
121120
startSpb.Append(IscCodes.isc_spb_bkp_parallel_workers, ConnectionStringOptions.ParallelWorkers);
122121
await StartTaskAsync(startSpb, cancellationToken).ConfigureAwait(false);

src/FirebirdSql.Data.FirebirdClient/Services/FbRestore.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ public int? PageSize
4646
public bool ReadOnly { get; set; }
4747
public string SkipData { get; set; }
4848
public FbRestoreFlags Options { get; set; }
49-
public bool IncludeStatistics { get; set; } = true;
50-
public FbBackupRestoreStatistics Statistics { get; set; }
49+
public FbBackupRestoreStatistics? Statistics { get; set; }
5150

5251
public FbRestore(string connectionString = null)
5352
: base(connectionString)
@@ -83,8 +82,8 @@ public void Execute()
8382
if (!string.IsNullOrEmpty(SkipData))
8483
startSpb.Append2(IscCodes.isc_spb_res_skip_data, SkipData);
8584
startSpb.Append(IscCodes.isc_spb_options, (int)Options);
86-
if (IncludeStatistics)
87-
startSpb.Append2(IscCodes.isc_spb_res_stat, Statistics.BuildConfiguration());
85+
if (Statistics.HasValue)
86+
startSpb.Append2(IscCodes.isc_spb_res_stat, Statistics.Value.BuildConfiguration());
8887
if (ConnectionStringOptions.ParallelWorkers > 0)
8988
startSpb.Append(IscCodes.isc_spb_res_parallel_workers, ConnectionStringOptions.ParallelWorkers);
9089
StartTask(startSpb);
@@ -131,8 +130,8 @@ public async Task ExecuteAsync(CancellationToken cancellationToken = default)
131130
if (!string.IsNullOrEmpty(SkipData))
132131
startSpb.Append2(IscCodes.isc_spb_res_skip_data, SkipData);
133132
startSpb.Append(IscCodes.isc_spb_options, (int)Options);
134-
if (IncludeStatistics)
135-
startSpb.Append2(IscCodes.isc_spb_res_stat, Statistics.BuildConfiguration());
133+
if (Statistics.HasValue)
134+
startSpb.Append2(IscCodes.isc_spb_res_stat, Statistics.Value.BuildConfiguration());
136135
if (ConnectionStringOptions.ParallelWorkers > 0)
137136
startSpb.Append(IscCodes.isc_spb_res_parallel_workers, ConnectionStringOptions.ParallelWorkers);
138137
await StartTaskAsync(startSpb, cancellationToken).ConfigureAwait(false);
Lines changed: 105 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,105 @@
1-
/*
2-
* The contents of this file are subject to the Initial
3-
* Developer's Public License Version 1.0 (the "License");
4-
* you may not use this file except in compliance with the
5-
* License. You may obtain a copy of the License at
6-
* https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt.
7-
*
8-
* Software distributed under the License is distributed on
9-
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10-
* express or implied. See the License for the specific
11-
* language governing rights and limitations under the License.
12-
*
13-
* All Rights Reserved.
14-
*/
15-
16-
//$Authors = Jiri Cincura ([email protected])
17-
18-
using System;
19-
using System.Runtime.InteropServices;
20-
21-
namespace FirebirdSql.Data.Types;
22-
23-
[StructLayout(LayoutKind.Auto)]
24-
public readonly struct FbZonedDateTime : IEquatable<FbZonedDateTime>
25-
{
26-
public DateTime DateTime { get; }
27-
public string TimeZone { get; }
28-
public TimeSpan? Offset { get; }
29-
30-
internal FbZonedDateTime(DateTime dateTime, string timeZone, TimeSpan? offset)
31-
{
32-
if (dateTime.Kind != DateTimeKind.Utc)
33-
throw new ArgumentException("Value must be in UTC.", nameof(dateTime));
34-
if (timeZone == null)
35-
throw new ArgumentNullException(nameof(timeZone));
36-
if (string.IsNullOrWhiteSpace(timeZone))
37-
throw new ArgumentException(nameof(timeZone));
38-
39-
DateTime = dateTime;
40-
TimeZone = timeZone;
41-
Offset = offset;
42-
}
43-
44-
public FbZonedDateTime(DateTime dateTime, string timeZone)
45-
: this(dateTime, timeZone, null)
46-
{ }
47-
48-
public override string ToString()
49-
{
50-
if (Offset != null)
51-
{
52-
return $"{DateTime} {TimeZone} ({Offset})";
53-
}
54-
return $"{DateTime} {TimeZone}";
55-
}
56-
57-
public override bool Equals(object obj)
58-
{
59-
return obj is FbZonedDateTime fbZonedDateTime && Equals(fbZonedDateTime);
60-
}
61-
62-
public override int GetHashCode()
63-
{
64-
unchecked
65-
{
66-
var hash = (int)2166136261;
67-
hash = (hash * 16777619) ^ DateTime.GetHashCode();
68-
hash = (hash * 16777619) ^ TimeZone.GetHashCode();
69-
if (Offset != null)
70-
hash = (hash * 16777619) ^ Offset.GetHashCode();
71-
return hash;
72-
}
73-
}
74-
75-
public bool Equals(FbZonedDateTime other) => DateTime.Equals(other.DateTime) && TimeZone.Equals(other.TimeZone, StringComparison.OrdinalIgnoreCase);
76-
77-
public static bool operator ==(FbZonedDateTime lhs, FbZonedDateTime rhs) => lhs.Equals(rhs);
78-
79-
public static bool operator !=(FbZonedDateTime lhs, FbZonedDateTime rhs) => lhs.Equals(rhs);
80-
}
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura ([email protected])
17+
18+
using System;
19+
using System.Runtime.InteropServices;
20+
21+
namespace FirebirdSql.Data.Types;
22+
23+
[StructLayout(LayoutKind.Auto)]
24+
public readonly struct FbZonedDateTime : IEquatable<FbZonedDateTime>, IConvertible
25+
{
26+
public DateTime DateTime { get; }
27+
public string TimeZone { get; }
28+
public TimeSpan? Offset { get; }
29+
30+
internal FbZonedDateTime(DateTime dateTime, string timeZone, TimeSpan? offset)
31+
{
32+
if (dateTime.Kind != DateTimeKind.Utc)
33+
throw new ArgumentException("Value must be in UTC.", nameof(dateTime));
34+
if (timeZone == null)
35+
throw new ArgumentNullException(nameof(timeZone));
36+
if (string.IsNullOrWhiteSpace(timeZone))
37+
throw new ArgumentException(nameof(timeZone));
38+
39+
DateTime = dateTime;
40+
TimeZone = timeZone;
41+
Offset = offset;
42+
}
43+
44+
public FbZonedDateTime(DateTime dateTime, string timeZone)
45+
: this(dateTime, timeZone, null)
46+
{ }
47+
48+
public override string ToString()
49+
{
50+
if (Offset != null)
51+
{
52+
return $"{DateTime} {TimeZone} ({Offset})";
53+
}
54+
return $"{DateTime} {TimeZone}";
55+
}
56+
57+
public override bool Equals(object obj)
58+
{
59+
return obj is FbZonedDateTime fbZonedDateTime && Equals(fbZonedDateTime);
60+
}
61+
62+
public override int GetHashCode()
63+
{
64+
unchecked
65+
{
66+
var hash = (int)2166136261;
67+
hash = (hash * 16777619) ^ DateTime.GetHashCode();
68+
hash = (hash * 16777619) ^ TimeZone.GetHashCode();
69+
if (Offset != null)
70+
hash = (hash * 16777619) ^ Offset.GetHashCode();
71+
return hash;
72+
}
73+
}
74+
75+
public bool Equals(FbZonedDateTime other) => DateTime.Equals(other.DateTime) && TimeZone.Equals(other.TimeZone, StringComparison.OrdinalIgnoreCase);
76+
77+
TypeCode IConvertible.GetTypeCode() => TypeCode.Object;
78+
79+
DateTime IConvertible.ToDateTime(IFormatProvider provider) => DateTime;
80+
81+
string IConvertible.ToString(IFormatProvider provider) => ToString();
82+
83+
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
84+
=> ReferenceEquals(conversionType, typeof(FbZonedDateTime))
85+
? this
86+
: throw new InvalidCastException(conversionType?.FullName);
87+
88+
bool IConvertible.ToBoolean(IFormatProvider provider) => throw new InvalidCastException(nameof(Boolean));
89+
byte IConvertible.ToByte(IFormatProvider provider) => throw new InvalidCastException(nameof(Byte));
90+
char IConvertible.ToChar(IFormatProvider provider) => throw new InvalidCastException(nameof(Char));
91+
decimal IConvertible.ToDecimal(IFormatProvider provider) => throw new InvalidCastException(nameof(Decimal));
92+
double IConvertible.ToDouble(IFormatProvider provider) => throw new InvalidCastException(nameof(Double));
93+
short IConvertible.ToInt16(IFormatProvider provider) => throw new InvalidCastException(nameof(Int16));
94+
int IConvertible.ToInt32(IFormatProvider provider) => throw new InvalidCastException(nameof(Int32));
95+
long IConvertible.ToInt64(IFormatProvider provider) => throw new InvalidCastException(nameof(Int64));
96+
sbyte IConvertible.ToSByte(IFormatProvider provider) => throw new InvalidCastException(nameof(SByte));
97+
float IConvertible.ToSingle(IFormatProvider provider) => throw new InvalidCastException(nameof(Single));
98+
ushort IConvertible.ToUInt16(IFormatProvider provider) => throw new InvalidCastException(nameof(UInt16));
99+
uint IConvertible.ToUInt32(IFormatProvider provider) => throw new InvalidCastException(nameof(UInt32));
100+
ulong IConvertible.ToUInt64(IFormatProvider provider) => throw new InvalidCastException(nameof(UInt64));
101+
102+
public static bool operator ==(FbZonedDateTime lhs, FbZonedDateTime rhs) => lhs.Equals(rhs);
103+
104+
public static bool operator !=(FbZonedDateTime lhs, FbZonedDateTime rhs) => lhs.Equals(rhs);
105+
}

0 commit comments

Comments
 (0)