1- using Google . Protobuf ;
2- using Google . Protobuf . WellKnownTypes ;
1+ using static Ydb . Sdk . Ado . Internal . YdbTypeExtensions ;
2+ using static Ydb . Sdk . Ado . Internal . YdbValueExtensions ;
33
44namespace Ydb . Sdk . Ado . Internal ;
55
66internal static class YdbTypedValueExtensions
77{
8- private const byte MaxPrecisionDecimal = 29 ;
9- private static readonly decimal [ ] Pow10 = CreatePow10 ( ) ;
10-
11- private static decimal [ ] CreatePow10 ( )
12- {
13- var a = new decimal [ 29 ] ;
14- a [ 0 ] = 1m ;
15- for ( var i = 1 ; i < a . Length ; i ++ ) a [ i ] = a [ i - 1 ] * 10m ; // 1..1e28
16- return a ;
17- }
18-
19- internal static TypedValue Null ( this Type . Types . PrimitiveTypeId primitiveTypeId ) => new ( )
20- {
21- Type = new Type { OptionalType = new OptionalType { Item = new Type { TypeId = primitiveTypeId } } } ,
22- Value = new Ydb . Value { NullFlagValue = NullValue . NullValue }
23- } ;
8+ private static readonly TypedValue DecimalDefaultNull = DecimalNull ( DefaultDecimalPrecision , DefaultDecimalScale ) ;
249
2510 internal static string ToYql ( this TypedValue typedValue ) => ToYql ( typedValue . Type ) ;
2611
@@ -35,166 +20,35 @@ private static string ToYql(Type type) =>
3520 _ => "Unknown"
3621 } ;
3722
38- internal static TypedValue NullDecimal ( byte precision , byte scale ) => new ( )
39- {
40- Type = new Type
41- {
42- OptionalType = new OptionalType
43- {
44- Item = new Type { DecimalType = new DecimalType { Precision = precision , Scale = scale } }
45- }
46- } ,
47- Value = new Ydb . Value { NullFlagValue = NullValue . NullValue }
48- } ;
49-
50- internal static TypedValue Text ( this string value ) => MakeText ( Type . Types . PrimitiveTypeId . Utf8 , value ) ;
51-
52- internal static TypedValue Bool ( this bool value ) =>
53- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Bool , new Ydb . Value { BoolValue = value } ) ;
54-
55- internal static TypedValue Int8 ( this sbyte value ) =>
56- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Int8 , new Ydb . Value { Int32Value = value } ) ;
57-
58- internal static TypedValue Int16 ( this short value ) =>
59- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Int16 , new Ydb . Value { Int32Value = value } ) ;
60-
61- internal static TypedValue Int32 ( this int value ) =>
62- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Int32 , new Ydb . Value { Int32Value = value } ) ;
63-
64- internal static TypedValue Int64 ( this long value ) =>
65- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Int64 , new Ydb . Value { Int64Value = value } ) ;
66-
67- internal static TypedValue Uint8 ( this byte value ) =>
68- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Uint8 , new Ydb . Value { Uint32Value = value } ) ;
69-
70- internal static TypedValue Uint16 ( this ushort value ) =>
71- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Uint16 , new Ydb . Value { Uint32Value = value } ) ;
72-
73- internal static TypedValue Uint32 ( this uint value ) =>
74- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Uint32 , new Ydb . Value { Uint32Value = value } ) ;
75-
76- internal static TypedValue Uint64 ( this ulong value ) =>
77- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Uint64 , new Ydb . Value { Uint64Value = value } ) ;
78-
79- internal static TypedValue Float ( this float value ) =>
80- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Float , new Ydb . Value { FloatValue = value } ) ;
81-
82- internal static TypedValue Double ( this double value ) =>
83- MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Double , new Ydb . Value { DoubleValue = value } ) ;
84-
85- internal static TypedValue Decimal ( this decimal value , byte precision , byte scale )
23+ internal static TypedValue List ( this IEnumerable < TypedValue > values )
8624 {
87- if ( scale > precision )
88- throw new ArgumentOutOfRangeException ( nameof ( scale ) , "Scale cannot exceed precision" ) ;
89-
90- var origScale = ( decimal . GetBits ( value ) [ 3 ] >> 16 ) & 0xFF ;
91-
92- if ( origScale > scale || ( precision < MaxPrecisionDecimal && Pow10 [ precision - scale ] <= Math . Abs ( value ) ) )
93- {
94- throw new OverflowException ( $ "Value { value } does not fit Decimal({ precision } , { scale } )") ;
95- }
96-
97- value *= 1.0000000000000000000000000000m ; // 28 zeros, max supported by c# decimal
98- value = Math . Round ( value , scale ) ;
99- var bits = decimal . GetBits ( value ) ;
100- var low = ( ( ulong ) ( uint ) bits [ 1 ] << 32 ) | ( uint ) bits [ 0 ] ;
101- var high = ( ulong ) ( uint ) bits [ 2 ] ;
102- var isNegative = bits [ 3 ] < 0 ;
25+ TypedValue ? first = null ;
26+ var value = new Ydb . Value ( ) ;
10327
104- unchecked
28+ foreach ( var v in values )
10529 {
106- if ( isNegative )
30+ first ??= v ;
31+ if ( first . Type . Equals ( v . Type ) )
10732 {
108- low = ~ low + 1UL ;
109- high = ~ high + ( low == 0 ? 1UL : 0UL ) ;
33+ throw new InvalidOperationException ( ) ;
11034 }
111- }
112-
113- return new TypedValue
114- {
115- Type = new Type { DecimalType = new DecimalType { Precision = precision , Scale = scale } } ,
116- Value = new Ydb . Value { Low128 = low , High128 = high }
117- } ;
118- }
119-
120- internal static TypedValue Bytes ( this byte [ ] value ) => MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . String ,
121- new Ydb . Value { BytesValue = ByteString . CopyFrom ( value ) } ) ;
122-
123- internal static TypedValue Yson ( this byte [ ] value ) => MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Yson ,
124- new Ydb . Value { BytesValue = ByteString . CopyFrom ( value ) } ) ;
125-
126- internal static TypedValue Json ( this string value ) => MakeText ( Type . Types . PrimitiveTypeId . Json , value ) ;
127-
128- internal static TypedValue JsonDocument ( this string value ) =>
129- MakeText ( Type . Types . PrimitiveTypeId . JsonDocument , value ) ;
130-
131- internal static TypedValue Uuid ( this Guid value )
132- {
133- var bytes = value . ToByteArray ( ) ;
134- var low = BitConverter . ToUInt64 ( bytes , 0 ) ;
135- var high = BitConverter . ToUInt64 ( bytes , 8 ) ;
136-
137- return MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Uuid , new Ydb . Value { Low128 = low , High128 = high } ) ;
138- }
139-
140- internal static TypedValue Date ( this DateTime value ) => MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Date ,
141- new Ydb . Value { Uint32Value = ( uint ) ( value . Subtract ( DateTime . UnixEpoch ) . Ticks / TimeSpan . TicksPerDay ) } ) ;
14235
143- internal static TypedValue Date32 ( this DateTime value ) => MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId . Date32 ,
144- new Ydb . Value { Int32Value = ( int ) ( value . Subtract ( DateTime . UnixEpoch ) . Ticks / TimeSpan . TicksPerDay ) } ) ;
145-
146- internal static TypedValue Datetime ( this DateTime dateTimeValue ) => MakePrimitiveTypedValue (
147- Type . Types . PrimitiveTypeId . Datetime , new Ydb . Value
148- { Uint32Value = ( uint ) ( dateTimeValue . Subtract ( DateTime . UnixEpoch ) . Ticks / TimeSpan . TicksPerSecond ) }
149- ) ;
150-
151- internal static TypedValue Datetime64 ( this DateTime dateTimeValue ) => MakePrimitiveTypedValue (
152- Type . Types . PrimitiveTypeId . Datetime64 ,
153- new Ydb . Value { Int64Value = dateTimeValue . Subtract ( DateTime . UnixEpoch ) . Ticks / TimeSpan . TicksPerSecond }
154- ) ;
155-
156- internal static TypedValue Timestamp ( this DateTime dateTimeValue ) => MakePrimitiveTypedValue (
157- Type . Types . PrimitiveTypeId . Timestamp , new Ydb . Value
158- {
159- Uint64Value = ( ulong ) ( dateTimeValue . Ticks - DateTime . UnixEpoch . Ticks ) / TimeSpanUtils . TicksPerMicrosecond
36+ value . Items . Add ( v . Value ) ;
16037 }
161- ) ;
162-
163- internal static TypedValue Timestamp64 ( this DateTime dateTimeValue ) => MakePrimitiveTypedValue (
164- Type . Types . PrimitiveTypeId . Timestamp64 , new Ydb . Value
165- { Int64Value = ( dateTimeValue . Ticks - DateTime . UnixEpoch . Ticks ) / TimeSpanUtils . TicksPerMicrosecond }
166- ) ;
167-
168- internal static TypedValue Interval ( this TimeSpan timeSpanValue ) => MakePrimitiveTypedValue (
169- Type . Types . PrimitiveTypeId . Interval ,
170- new Ydb . Value { Int64Value = timeSpanValue . Ticks / TimeSpanUtils . TicksPerMicrosecond }
171- ) ;
172-
173- internal static TypedValue Interval64 ( this TimeSpan timeSpanValue ) => MakePrimitiveTypedValue (
174- Type . Types . PrimitiveTypeId . Interval64 ,
175- new Ydb . Value { Int64Value = timeSpanValue . Ticks / TimeSpanUtils . TicksPerMicrosecond }
176- ) ;
17738
178- internal static TypedValue List ( this IReadOnlyList < TypedValue > values )
179- {
180- if ( values . Count == 0 )
181- {
182- throw new ArgumentOutOfRangeException ( nameof ( values ) ) ;
183- }
39+ if ( first is null ) throw new ArgumentOutOfRangeException ( nameof ( values ) ) ;
18440
185- var value = new Ydb . Value ( ) ;
186- value . Items . Add ( values . Select ( v => v . Value ) ) ;
41+ return new TypedValue { Type = ListType ( first . Type ) , Value = value } ;
42+ }
18743
188- return new TypedValue
44+ internal static TypedValue DecimalNull ( byte precision , byte scale ) => precision == 0 && scale == 0
45+ ? DecimalDefaultNull
46+ : new TypedValue
18947 {
190- Type = new Type { ListType = new ListType { Item = values [ 0 ] . Type } } ,
191- Value = value
48+ Type = new Type { OptionalType = new OptionalType { Item = DecimalType ( precision , scale ) } } ,
49+ Value = YdbValueNull
19250 } ;
193- }
194-
195- private static TypedValue MakeText ( Type . Types . PrimitiveTypeId primitiveTypeId , string textValue ) =>
196- MakePrimitiveTypedValue ( primitiveTypeId , new Ydb . Value { TextValue = textValue } ) ;
19751
198- private static TypedValue MakePrimitiveTypedValue ( Type . Types . PrimitiveTypeId primitiveTypeId , Ydb . Value value ) =>
199- new ( ) { Type = new Type { TypeId = primitiveTypeId } , Value = value } ;
52+ internal static TypedValue ListNull ( Type type ) => new ( )
53+ { Type = new Type { OptionalType = { Item = ListType ( type ) } } , Value = YdbValueNull } ;
20054}
0 commit comments