@@ -21,11 +21,22 @@ template <bool IsOptional>
21
21
class TFromBytesWrapper : public TMutableComputationNode <TFromBytesWrapper<IsOptional>> {
22
22
typedef TMutableComputationNode<TFromBytesWrapper<IsOptional>> TBaseComputation;
23
23
public:
24
- TFromBytesWrapper (TComputationMutables& mutables, IComputationNode* data, NUdf::TDataTypeId schemeType)
24
+ TFromBytesWrapper (TComputationMutables& mutables, IComputationNode* data, NUdf::TDataTypeId schemeType, ui32 param1, ui32 param2 )
25
25
: TBaseComputation(mutables)
26
26
, Data(data)
27
27
, SchemeType(NUdf::GetDataSlot(schemeType))
28
+ , Param1(param1)
29
+ , Param2(param2)
28
30
{
31
+ if (SchemeType == NUdf::EDataSlot::Decimal) {
32
+ DecimalBound = NYql::NDecimal::TInt128 (1 );
33
+ NYql::NDecimal::TInt128 ten (10U );
34
+ for (ui32 i = 0 ; i < Param1; ++i) {
35
+ DecimalBound *= ten;
36
+ }
37
+
38
+ NegDecimalBound = -DecimalBound;
39
+ }
29
40
}
30
41
31
42
NUdf::TUnboxedValuePod DoCalculate (TComputationContext& ctx) const {
@@ -36,10 +47,6 @@ class TFromBytesWrapper : public TMutableComputationNode<TFromBytesWrapper<IsOpt
36
47
37
48
switch (SchemeType) {
38
49
case NUdf::EDataSlot::TzDate: {
39
- if (!data) {
40
- return NUdf::TUnboxedValuePod ();
41
- }
42
-
43
50
const auto & ref = data.AsStringRef ();
44
51
if (ref.Size () != 4 ) {
45
52
return NUdf::TUnboxedValuePod ();
@@ -57,10 +64,6 @@ class TFromBytesWrapper : public TMutableComputationNode<TFromBytesWrapper<IsOpt
57
64
}
58
65
59
66
case NUdf::EDataSlot::TzDatetime: {
60
- if (!data) {
61
- return NUdf::TUnboxedValuePod ();
62
- }
63
-
64
67
const auto & ref = data.AsStringRef ();
65
68
if (ref.Size () != 6 ) {
66
69
return NUdf::TUnboxedValuePod ();
@@ -78,18 +81,65 @@ class TFromBytesWrapper : public TMutableComputationNode<TFromBytesWrapper<IsOpt
78
81
}
79
82
80
83
case NUdf::EDataSlot::TzTimestamp: {
81
- if (!data) {
84
+ const auto & ref = data.AsStringRef ();
85
+ if (ref.Size () != 10 ) {
82
86
return NUdf::TUnboxedValuePod ();
83
87
}
84
88
89
+ auto tzId = SwapBytes (ReadUnaligned<ui16>(ref.Data () + ref.Size () - sizeof (ui16)));
90
+ auto value = SwapBytes (data.Get <ui64>());
91
+ if (value < NUdf::MAX_TIMESTAMP && tzId < NUdf::GetTimezones ().size ()) {
92
+ auto ret = NUdf::TUnboxedValuePod (value);
93
+ ret.SetTimezoneId (tzId);
94
+ return ret;
95
+ }
96
+
97
+ return NUdf::TUnboxedValuePod ();
98
+ }
99
+
100
+ case NUdf::EDataSlot::TzDate32: {
101
+ const auto & ref = data.AsStringRef ();
102
+ if (ref.Size () != 6 ) {
103
+ return NUdf::TUnboxedValuePod ();
104
+ }
105
+
106
+ auto tzId = SwapBytes (ReadUnaligned<ui16>(ref.Data () + ref.Size () - sizeof (ui16)));
107
+ auto value = SwapBytes (data.Get <i32 >());
108
+ if (value >= NUdf::MIN_DATE32 && value <= NUdf::MAX_DATE32 && tzId < NUdf::GetTimezones ().size ()) {
109
+ auto ret = NUdf::TUnboxedValuePod (value);
110
+ ret.SetTimezoneId (tzId);
111
+ return ret;
112
+ }
113
+
114
+ return NUdf::TUnboxedValuePod ();
115
+ }
116
+
117
+ case NUdf::EDataSlot::TzDatetime64: {
85
118
const auto & ref = data.AsStringRef ();
86
119
if (ref.Size () != 10 ) {
87
120
return NUdf::TUnboxedValuePod ();
88
121
}
89
122
90
123
auto tzId = SwapBytes (ReadUnaligned<ui16>(ref.Data () + ref.Size () - sizeof (ui16)));
91
- auto value = SwapBytes (data.Get <ui64>());
92
- if (value < NUdf::MAX_TIMESTAMP && tzId < NUdf::GetTimezones ().size ()) {
124
+ auto value = SwapBytes (data.Get <i64 >());
125
+ if (value >= NUdf::MIN_DATETIME64 && value <= NUdf::MAX_DATETIME64 && tzId < NUdf::GetTimezones ().size ()) {
126
+ auto ret = NUdf::TUnboxedValuePod (value);
127
+ ret.SetTimezoneId (tzId);
128
+ return ret;
129
+ }
130
+
131
+ return NUdf::TUnboxedValuePod ();
132
+ }
133
+
134
+ case NUdf::EDataSlot::TzTimestamp64: {
135
+ const auto & ref = data.AsStringRef ();
136
+ if (ref.Size () != 10 ) {
137
+ return NUdf::TUnboxedValuePod ();
138
+ }
139
+
140
+ auto tzId = SwapBytes (ReadUnaligned<ui16>(ref.Data () + ref.Size () - sizeof (ui16)));
141
+ auto value = SwapBytes (data.Get <i64 >());
142
+ if (value >= NUdf::MIN_TIMESTAMP64 && value <= NUdf::MAX_TIMESTAMP64 && tzId < NUdf::GetTimezones ().size ()) {
93
143
auto ret = NUdf::TUnboxedValuePod (value);
94
144
ret.SetTimezoneId (tzId);
95
145
return ret;
@@ -105,6 +155,35 @@ class TFromBytesWrapper : public TMutableComputationNode<TFromBytesWrapper<IsOpt
105
155
return data.Release ();
106
156
}
107
157
158
+ case NUdf::EDataSlot::Decimal: {
159
+ const auto & ref = data.AsStringRef ();
160
+ if (ref.Size () != 15 ) {
161
+ return NUdf::TUnboxedValuePod ();
162
+ }
163
+
164
+ NYql::NDecimal::TInt128 v = 0 ;
165
+ ui8* p = (ui8*)&v;
166
+ memcpy (p, ref.Data (), 15 );
167
+ p[0xF ] = (p[0xE ] & 0x80 ) ? 0xFF : 0x00 ;
168
+ if (NYql::NDecimal::IsError (v)) {
169
+ return NUdf::TUnboxedValuePod ();
170
+ }
171
+
172
+ if (!NYql::NDecimal::IsNormal (v)) {
173
+ return NUdf::TUnboxedValuePod (v);
174
+ }
175
+
176
+ if (v >= DecimalBound) {
177
+ return NUdf::TUnboxedValuePod (NYql::NDecimal::Inf ());
178
+ }
179
+
180
+ if (v <= NegDecimalBound) {
181
+ return NUdf::TUnboxedValuePod (-NYql::NDecimal::Inf ());
182
+ }
183
+
184
+ return NUdf::TUnboxedValuePod (v);
185
+ }
186
+
108
187
default :
109
188
if (IsValidValue (SchemeType, data)) {
110
189
return data.Release ();
@@ -121,25 +200,39 @@ class TFromBytesWrapper : public TMutableComputationNode<TFromBytesWrapper<IsOpt
121
200
122
201
IComputationNode* const Data;
123
202
const NUdf::EDataSlot SchemeType;
203
+ const ui32 Param1;
204
+ const ui32 Param2;
205
+ NYql::NDecimal::TInt128 DecimalBound, NegDecimalBound;
124
206
};
125
207
126
208
}
127
209
128
210
IComputationNode* WrapFromBytes (TCallable& callable, const TComputationNodeFactoryContext& ctx) {
129
- MKQL_ENSURE (callable.GetInputsCount () == 2 , " Expected 2 args" );
211
+ MKQL_ENSURE (callable.GetInputsCount () == 2 || callable. GetInputsCount () == 4 , " Expected 2 or 4 args" );
130
212
131
213
bool isOptional;
132
214
const auto dataType = UnpackOptionalData (callable.GetInput (0 ), isOptional);
133
215
MKQL_ENSURE (dataType->GetSchemeType () == NUdf::TDataType<char *>::Id, " Expected String" );
134
216
135
217
const auto schemeTypeData = AS_VALUE (TDataLiteral, callable.GetInput (1 ));
136
218
const auto schemeType = schemeTypeData->AsValue ().Get <ui32>();
219
+ ui32 param1 = 0 ;
220
+ ui32 param2 = 0 ;
221
+ if (schemeType == NUdf::TDataType<NUdf::TDecimal>::Id) {
222
+ MKQL_ENSURE (callable.GetInputsCount () == 4 , " Expected 4 args" );
223
+ const auto param1Data = AS_VALUE (TDataLiteral, callable.GetInput (2 ));
224
+ param1 = param1Data->AsValue ().Get <ui32>();
225
+ const auto param2Data = AS_VALUE (TDataLiteral, callable.GetInput (3 ));
226
+ param2 = param2Data->AsValue ().Get <ui32>();
227
+ } else {
228
+ MKQL_ENSURE (callable.GetInputsCount () == 2 , " Expected 2 args" );
229
+ }
137
230
138
231
const auto data = LocateNode (ctx.NodeLocator , callable, 0 );
139
232
if (isOptional) {
140
- return new TFromBytesWrapper<true >(ctx.Mutables , data, static_cast <NUdf::TDataTypeId>(schemeType));
233
+ return new TFromBytesWrapper<true >(ctx.Mutables , data, static_cast <NUdf::TDataTypeId>(schemeType), param1, param2 );
141
234
} else {
142
- return new TFromBytesWrapper<false >(ctx.Mutables , data, static_cast <NUdf::TDataTypeId>(schemeType));
235
+ return new TFromBytesWrapper<false >(ctx.Mutables , data, static_cast <NUdf::TDataTypeId>(schemeType), param1, param2 );
143
236
}
144
237
}
145
238
0 commit comments