Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
ports: [ "2135:2135", "2136:2136", "8765:8765" ]
env:
YDB_LOCAL_SURVIVE_RESTART: true
YDB_FEATURE_FLAGS: enable_parameterized_decimal
YDB_FEATURE_FLAGS: enable_parameterized_decimal,enable_table_datetime64
options: '--name ydb-local -h localhost'

steps:
Expand Down
2 changes: 2 additions & 0 deletions src/Ydb.Sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- Feat ADO.NET: Deleted support for `DateTimeOffset` was a mistake.
- Feat ADO.NET: Added support for `Date32`, `Datetime64`, `Timestamp64` and `Interval64` types in YDB.
- Feat: Implement `YdbRetryPolicy` with AWS-inspired Exponential Backoff and Jitter.
- Dev: LogLevel `Warning` -> `Debug` on DeleteSession has been `RpcException`.

Expand Down
2 changes: 0 additions & 2 deletions src/Ydb.Sdk/src/Ado/Internal/SqlParam.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using Ydb.Sdk.Ado.YdbType;

namespace Ydb.Sdk.Ado.Internal;

internal interface ISqlParam
Expand Down
6 changes: 6 additions & 0 deletions src/Ydb.Sdk/src/Ado/Internal/TimeSpanConsts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Ydb.Sdk.Ado.Internal;

internal static class TimeSpanUtils
{
internal const long TicksPerMicrosecond = TimeSpan.TicksPerMillisecond / 1000;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;

namespace Ydb.Sdk.Ado.YdbType;
namespace Ydb.Sdk.Ado.Internal;

internal static class YdbTypedValueExtensions
{
Expand Down Expand Up @@ -123,22 +123,39 @@ internal static TypedValue Uuid(this Guid value)
internal static TypedValue Date(this DateTime value) => MakePrimitiveTypedValue(Type.Types.PrimitiveTypeId.Date,
new Ydb.Value { Uint32Value = (uint)(value.Subtract(DateTime.UnixEpoch).Ticks / TimeSpan.TicksPerDay) });

internal static TypedValue Date32(this DateTime value) => MakePrimitiveTypedValue(Type.Types.PrimitiveTypeId.Date32,
new Ydb.Value { Int32Value = (int)(value.Subtract(DateTime.UnixEpoch).Ticks / TimeSpan.TicksPerDay) });

internal static TypedValue Datetime(this DateTime dateTimeValue) => MakePrimitiveTypedValue(
Type.Types.PrimitiveTypeId.Datetime,
new Ydb.Value
Type.Types.PrimitiveTypeId.Datetime, new Ydb.Value
{ Uint32Value = (uint)(dateTimeValue.Subtract(DateTime.UnixEpoch).Ticks / TimeSpan.TicksPerSecond) }
);

internal static TypedValue Datetime64(this DateTime dateTimeValue) => MakePrimitiveTypedValue(
Type.Types.PrimitiveTypeId.Datetime64,
new Ydb.Value { Int64Value = dateTimeValue.Subtract(DateTime.UnixEpoch).Ticks / TimeSpan.TicksPerSecond }
);

internal static TypedValue Timestamp(this DateTime dateTimeValue) => MakePrimitiveTypedValue(
Type.Types.PrimitiveTypeId.Timestamp, new Ydb.Value
{
Uint64Value = (ulong)(dateTimeValue.Ticks - DateTime.UnixEpoch.Ticks) * Duration.NanosecondsPerTick / 1000
Uint64Value = (ulong)(dateTimeValue.Ticks - DateTime.UnixEpoch.Ticks) / TimeSpanUtils.TicksPerMicrosecond
}
);

internal static TypedValue Timestamp64(this DateTime dateTimeValue) => MakePrimitiveTypedValue(
Type.Types.PrimitiveTypeId.Timestamp64, new Ydb.Value
{ Int64Value = (dateTimeValue.Ticks - DateTime.UnixEpoch.Ticks) / TimeSpanUtils.TicksPerMicrosecond }
);

internal static TypedValue Interval(this TimeSpan timeSpanValue) => MakePrimitiveTypedValue(
Type.Types.PrimitiveTypeId.Interval,
new Ydb.Value { Int64Value = timeSpanValue.Ticks * Duration.NanosecondsPerTick / 1000 }
new Ydb.Value { Int64Value = timeSpanValue.Ticks / TimeSpanUtils.TicksPerMicrosecond }
);

internal static TypedValue Interval64(this TimeSpan timeSpanValue) => MakePrimitiveTypedValue(
Type.Types.PrimitiveTypeId.Interval64,
new Ydb.Value { Int64Value = timeSpanValue.Ticks / TimeSpanUtils.TicksPerMicrosecond }
);

internal static TypedValue List(this IReadOnlyList<TypedValue> values)
Expand Down
101 changes: 101 additions & 0 deletions src/Ydb.Sdk/src/Ado/Internal/YdbValueExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
namespace Ydb.Sdk.Ado.Internal;

internal static class YdbValueExtensions
{
private static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);

internal static bool IsNull(this Ydb.Value value) => value.ValueCase == Ydb.Value.ValueOneofCase.NullFlagValue;

internal static bool GetBool(this Ydb.Value value) => value.BoolValue;

internal static sbyte GetInt8(this Ydb.Value value) => (sbyte)value.Int32Value;

internal static byte GetUint8(this Ydb.Value value) => (byte)value.Uint32Value;

internal static short GetInt16(this Ydb.Value value) => (short)value.Int32Value;

internal static ushort GetUint16(this Ydb.Value value) => (ushort)value.Uint32Value;

internal static int GetInt32(this Ydb.Value value) => value.Int32Value;

internal static uint GetUint32(this Ydb.Value value) => value.Uint32Value;

internal static long GetInt64(this Ydb.Value value) => value.Int64Value;

internal static ulong GetUint64(this Ydb.Value value) => value.Uint64Value;

internal static float GetFloat(this Ydb.Value value) => value.FloatValue;

internal static double GetDouble(this Ydb.Value value) => value.DoubleValue;

internal static DateTime GetDate(this Ydb.Value value) =>
UnixEpoch.AddTicks(value.Uint32Value * TimeSpan.TicksPerDay);

internal static DateTime GetDate32(this Ydb.Value value) =>
UnixEpoch.AddTicks(value.Int32Value * TimeSpan.TicksPerDay);

internal static DateTime GetDatetime(this Ydb.Value value) =>
UnixEpoch.AddTicks(value.Uint32Value * TimeSpan.TicksPerSecond);

internal static DateTime GetDatetime64(this Ydb.Value value) =>
UnixEpoch.AddTicks(value.Int64Value * TimeSpan.TicksPerSecond);

internal static DateTime GetTimestamp(this Ydb.Value value) =>
UnixEpoch.AddTicks((long)(value.Uint64Value * TimeSpanUtils.TicksPerMicrosecond));

internal static DateTime GetTimestamp64(this Ydb.Value value) =>
UnixEpoch.AddTicks(value.Int64Value * TimeSpanUtils.TicksPerMicrosecond);

internal static TimeSpan GetInterval(this Ydb.Value value) =>
TimeSpan.FromTicks(value.Int64Value * TimeSpanUtils.TicksPerMicrosecond);

internal static TimeSpan GetInterval64(this Ydb.Value value) =>
TimeSpan.FromTicks(value.Int64Value * TimeSpanUtils.TicksPerMicrosecond);

internal static byte[] GetBytes(this Ydb.Value value) => value.BytesValue.ToByteArray();

internal static string GetText(this Ydb.Value value) => value.TextValue;

internal static string GetJson(this Ydb.Value value) => value.TextValue;

internal static string GetJsonDocument(this Ydb.Value value) => value.TextValue;

internal static Guid GetUuid(this Ydb.Value value)
{
var high = value.High128;
var low = value.Low128;

var lowBytes = BitConverter.GetBytes(low);
var highBytes = BitConverter.GetBytes(high);

var guidBytes = new byte[16];
Array.Copy(lowBytes, 0, guidBytes, 0, 8);
Array.Copy(highBytes, 0, guidBytes, 8, 8);

return new Guid(guidBytes);
}

internal static decimal GetDecimal(this Ydb.Value value, uint scale)
{
var lo = value.Low128;
var hi = value.High128;
var isNegative = (hi & 0x8000_0000_0000_0000UL) != 0;
unchecked
{
if (isNegative)
{
if (lo == 0)
hi--;

lo--;
lo = ~lo;
hi = ~hi;
}
}

if (hi >> 32 != 0)
throw new OverflowException("Value does not fit into decimal");

return new decimal((int)lo, (int)(lo >> 32), (int)hi, isNegative, (byte)scale);
}
}
15 changes: 0 additions & 15 deletions src/Ydb.Sdk/src/Ado/ThrowHelper.cs

This file was deleted.

1 change: 0 additions & 1 deletion src/Ydb.Sdk/src/Ado/YdbCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Ydb.Sdk.Ado.Internal;
using Ydb.Sdk.Ado.YdbType;

namespace Ydb.Sdk.Ado;

Expand Down
Loading
Loading