@@ -22,197 +22,6 @@ namespace NGRpcService {
22
22
23
23
using TEvObjectStorageListingRequest = TGrpcRequestOperationCall<Ydb::ObjectStorage::ListingRequest, Ydb::ObjectStorage::ListingResponse>;
24
24
25
- #define CHECK_OR_RETURN_ERROR (cond, descr ) \
26
- if (!(cond)) { \
27
- errStr = descr; \
28
- return false ; \
29
- }
30
-
31
- bool CellFromTuple (NScheme::TTypeInfo type,
32
- const Ydb::Value& tupleValue,
33
- ui32 position,
34
- bool allowCastFromString,
35
- TVector<TCell>& cells,
36
- TString& errStr,
37
- TVector<TString>& memoryOwner) {
38
- auto value_case = tupleValue.value_case ();
39
-
40
- CHECK_OR_RETURN_ERROR (value_case != Ydb::Value::VALUE_NOT_SET,
41
- Sprintf (" Data must be present at position %" PRIu32, position));
42
-
43
- CHECK_OR_RETURN_ERROR (tupleValue.itemsSize () == 0 &&
44
- tupleValue.pairsSize () == 0 ,
45
- Sprintf (" Simple type is expected in tuple at position %" PRIu32, position));
46
-
47
- TCell c;
48
- auto typeId = type.GetTypeId ();
49
- switch (typeId) {
50
-
51
- #define CASE_SIMPLE_TYPE (name, type, protoField ) \
52
- case NScheme::NTypeIds::name: \
53
- { \
54
- bool valuePresent = tupleValue.Has ##protoField##_value (); \
55
- if (valuePresent) { \
56
- type val = tupleValue.Get ##protoField##_value (); \
57
- c = TCell ((const char *)&val, sizeof (val)); \
58
- } else if (allowCastFromString && tupleValue.Hastext_value ()) { \
59
- const auto slot = NUdf::GetDataSlot (typeId); \
60
- const auto out = NMiniKQL::ValueFromString (slot, tupleValue.Gettext_value ()); \
61
- CHECK_OR_RETURN_ERROR (out, Sprintf (" Cannot parse value of type " #name " from text '%s' in tuple at position %" PRIu32, tupleValue.Gettext_value ().data (), position)); \
62
- const auto val = out.Get <type>(); \
63
- c = TCell ((const char *)&val, sizeof (val)); \
64
- } else { \
65
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Value of type " #name " expected in tuple at position %" PRIu32, position)); \
66
- } \
67
- Y_ABORT_UNLESS (c.IsInline ()); \
68
- break ; \
69
- }
70
-
71
- CASE_SIMPLE_TYPE (Bool, bool , bool );
72
- CASE_SIMPLE_TYPE (Int8, i8 , int32);
73
- CASE_SIMPLE_TYPE (Uint8, ui8, uint32);
74
- CASE_SIMPLE_TYPE (Int16, i16 , int32);
75
- CASE_SIMPLE_TYPE (Uint16, ui16, uint32);
76
- CASE_SIMPLE_TYPE (Int32, i32 , int32);
77
- CASE_SIMPLE_TYPE (Uint32, ui32, uint32);
78
- CASE_SIMPLE_TYPE (Int64, i64 , int64);
79
- CASE_SIMPLE_TYPE (Uint64, ui64, uint64);
80
- CASE_SIMPLE_TYPE (Float, float , float );
81
- CASE_SIMPLE_TYPE (Double, double , double );
82
- CASE_SIMPLE_TYPE (Date, ui16, uint32);
83
- CASE_SIMPLE_TYPE (Datetime, ui32, uint32);
84
- CASE_SIMPLE_TYPE (Timestamp, ui64, uint64);
85
- CASE_SIMPLE_TYPE (Interval, i64 , int64);
86
-
87
-
88
- #undef CASE_SIMPLE_TYPE
89
-
90
- case NScheme::NTypeIds::Yson:
91
- case NScheme::NTypeIds::Json:
92
- case NScheme::NTypeIds::Utf8:
93
- {
94
- c = TCell (tupleValue.Gettext_value ().data (), tupleValue.Gettext_value ().size ());
95
- break ;
96
- }
97
- case NScheme::NTypeIds::JsonDocument:
98
- case NScheme::NTypeIds::DyNumber:
99
- {
100
- c = TCell (tupleValue.Getbytes_value ().data (), tupleValue.Getbytes_value ().size ());
101
- break ;
102
- }
103
- case NScheme::NTypeIds::String:
104
- {
105
- if (tupleValue.Hasbytes_value ()) {
106
- c = TCell (tupleValue.Getbytes_value ().data (), tupleValue.Getbytes_value ().size ());
107
- } else if (allowCastFromString && tupleValue.Hastext_value ()) {
108
- c = TCell (tupleValue.Gettext_value ().data (), tupleValue.Gettext_value ().size ());
109
- } else {
110
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Cannot parse value of type String in tuple at position %" PRIu32, position));
111
- }
112
- break ;
113
- }
114
- case NScheme::NTypeIds::Pg:
115
- {
116
- if (tupleValue.Hasbytes_value ()) {
117
- c = TCell (tupleValue.Getbytes_value ().data (), tupleValue.Getbytes_value ().size ());
118
- } else if (tupleValue.Hastext_value ()) {
119
- auto typeDesc = type.GetPgTypeDesc ();
120
- auto convert = NPg::PgNativeBinaryFromNativeText (tupleValue.Gettext_value (), NPg::PgTypeIdFromTypeDesc (typeDesc));
121
- if (convert.Error ) {
122
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Cannot parse value of type Pg: %s in tuple at position %" PRIu32, convert.Error ->data (), position));
123
- } else {
124
- auto &data = memoryOwner.emplace_back (convert.Str );
125
- c = TCell (data);
126
- }
127
- } else {
128
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Cannot parse value of type Pg in tuple at position %" PRIu32, position));
129
- }
130
- break ;
131
- }
132
- case NScheme::NTypeIds::Uuid:
133
- {
134
- if (tupleValue.Haslow_128 ()) {
135
- auto &data = memoryOwner.emplace_back ();
136
- data.resize (NUuid::UUID_LEN);
137
- NUuid::UuidHalfsToBytes (data.Detach (), data.size (), tupleValue.Gethigh_128 (), tupleValue.Getlow_128 ());
138
- c = TCell (data);
139
- } else if (tupleValue.Hasbytes_value ()) {
140
- Y_ABORT_UNLESS (tupleValue.Getbytes_value ().size () == NUuid::UUID_LEN);
141
- c = TCell (tupleValue.Getbytes_value ().data (), tupleValue.Getbytes_value ().size ());
142
- } else {
143
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Cannot parse value of type Uuid in tuple at position %" PRIu32, position));
144
- }
145
- break ;
146
- }
147
- case NScheme::NTypeIds::Decimal:
148
- {
149
- if (tupleValue.Haslow_128 ()) {
150
- NYql::NDecimal::TInt128 int128 = NYql::NDecimal::FromHalfs (tupleValue.Getlow_128 (), tupleValue.Gethigh_128 ());
151
- auto &data = memoryOwner.emplace_back ();
152
- data.resize (sizeof (NYql::NDecimal::TInt128));
153
- std::memcpy (data.Detach (), &int128, sizeof (NYql::NDecimal::TInt128));
154
- c = TCell (data);
155
- } else {
156
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Cannot parse value of type Decimal in tuple at position %" PRIu32, position));
157
- }
158
- break ;
159
- }
160
- default :
161
- CHECK_OR_RETURN_ERROR (false , Sprintf (" Unsupported typeId %" PRIu16 " at index %" PRIu32, typeId, position));
162
- break ;
163
- }
164
-
165
- CHECK_OR_RETURN_ERROR (!c.IsNull (), Sprintf (" Invalid non-NULL value at index %" PRIu32, position));
166
- cells.push_back (c);
167
-
168
- return true ;
169
- }
170
-
171
- // NOTE: TCell's can reference memory from tupleValue
172
- bool CellsFromTuple (const Ydb::Type* tupleType,
173
- const Ydb::Value& tupleValue,
174
- const TConstArrayRef<NScheme::TTypeInfo>& types,
175
- bool allowCastFromString,
176
- TVector<TCell>& key,
177
- TString& errStr,
178
- TVector<TString>& memoryOwner) {
179
- if (tupleType) {
180
- Ydb::Type::TypeCase typeCase = tupleType->type_case ();
181
- CHECK_OR_RETURN_ERROR (typeCase == Ydb::Type::kTupleType ||
182
- (typeCase == Ydb::Type::TYPE_NOT_SET && tupleType->tuple_type ().elementsSize () == 0 ), " Must be a tuple" );
183
- CHECK_OR_RETURN_ERROR (tupleType->tuple_type ().elementsSize () <= types.size (),
184
- " Tuple size " + ToString (tupleType->tuple_type ().elementsSize ()) + " is greater that expected size " + ToString (types.size ()));
185
-
186
- for (size_t i = 0 ; i < tupleType->tuple_type ().elementsSize (); ++i) {
187
- const auto & ti = tupleType->tuple_type ().Getelements (i);
188
- CHECK_OR_RETURN_ERROR (ti.type_case () == Ydb::Type::kTypeId , " Element at index " + ToString (i) + " in not a TypeId" );
189
- const auto & typeId = ti.Gettype_id ();
190
- CHECK_OR_RETURN_ERROR (typeId == types[i].GetTypeId () ||
191
- allowCastFromString && (typeId == NScheme::NTypeIds::Utf8),
192
- " Element at index " + ToString (i) + " has type " + Type_PrimitiveTypeId_Name (typeId) + " but expected type is " + ToString (types[i].GetTypeId ()));
193
- }
194
-
195
- CHECK_OR_RETURN_ERROR (tupleType->Gettuple_type ().elementsSize () == tupleValue.itemsSize (),
196
- Sprintf (" Tuple value length %" PRISZT " doesn't match the length in type %" PRISZT, tupleValue.itemsSize (), tupleType->Gettuple_type ().elementsSize ()));
197
- } else {
198
- CHECK_OR_RETURN_ERROR (types.size () >= tupleValue.itemsSize (),
199
- Sprintf (" Tuple length %" PRISZT " is greater than key column count %" PRISZT, tupleValue.itemsSize (), types.size ()));
200
- }
201
-
202
- for (ui32 i = 0 ; i < tupleValue.itemsSize (); ++i) {
203
- auto & v = tupleValue.Getitems (i);
204
-
205
- bool parsed = CellFromTuple (types[i], v, i, allowCastFromString, key, errStr, memoryOwner);
206
-
207
- if (!parsed) {
208
- return false ;
209
- }
210
- }
211
-
212
- return true ;
213
- }
214
- #undef CHECK_OR_RETURN_ERROR
215
-
216
25
struct TFilter {
217
26
TVector<ui32> ColumnIds;
218
27
TSerializedCellVec FilterValues;
@@ -240,6 +49,7 @@ class TObjectStorageListingRequestGrpc : public TActorBootstrapped<TObjectStorag
240
49
bool Finished;
241
50
TAutoPtr<NSchemeCache::TSchemeCacheNavigate> ResolveNamesResult;
242
51
TVector<NScheme::TTypeInfo> KeyColumnTypes;
52
+ TVector<TConversionTypeInfo> KeyColumnTypeInfos;
243
53
TSysTables::TTableColumnInfo PathColumnInfo;
244
54
TVector<TSysTables::TTableColumnInfo> CommonPrefixesColumns;
245
55
TVector<TSysTables::TTableColumnInfo> ContentsColumns;
@@ -409,15 +219,17 @@ class TObjectStorageListingRequestGrpc : public TActorBootstrapped<TObjectStorag
409
219
KeyColumnTypes[keyOrder] = ci.second .PType ;
410
220
keyColumnIds.resize (Max<size_t >(keyColumnIds.size (), keyOrder + 1 ));
411
221
keyColumnIds[keyOrder] = ci.second .Id ;
222
+ KeyColumnTypeInfos.resize (Max<size_t >(keyColumnIds.size (), keyOrder + 1 ));
223
+ KeyColumnTypeInfos[keyOrder] = {ci.second .PType , ci.second .PTypeMod , ci.second .IsNotNullColumn };
412
224
}
413
225
}
414
226
415
227
TString errStr;
416
228
TVector<TCell> prefixCells;
417
- TVector<TString> prefixMemoryOwner;
418
- TConstArrayRef<NScheme::TTypeInfo > prefixTypes (KeyColumnTypes .data (), KeyColumnTypes .size () - 1 ); // -1 for path column
229
+ TMemoryPool prefixMemoryOwner ( 256 ) ;
230
+ TConstArrayRef<TConversionTypeInfo > prefixTypes (KeyColumnTypeInfos .data (), KeyColumnTypeInfos .size () - 1 ); // -1 for path column
419
231
bool prefixParsedOk = CellsFromTuple (&Request->Getkey_prefix ().Gettype (), Request->Getkey_prefix ().Getvalue (),
420
- prefixTypes, true , prefixCells, errStr, prefixMemoryOwner);
232
+ prefixTypes, true , false , prefixCells, errStr, prefixMemoryOwner);
421
233
422
234
if (!prefixParsedOk) {
423
235
ReplyWithError (Ydb::StatusIds::BAD_REQUEST, " Invalid KeyPrefix: " + errStr, ctx);
@@ -440,10 +252,10 @@ class TObjectStorageListingRequestGrpc : public TActorBootstrapped<TObjectStorag
440
252
CommonPrefixesColumns.push_back (PathColumnInfo);
441
253
442
254
TVector<TCell> suffixCells;
443
- TVector<TString> suffixMemoryOwner;
444
- TConstArrayRef<NScheme::TTypeInfo > suffixTypes (KeyColumnTypes .data () + pathColPos, KeyColumnTypes .size () - pathColPos); // starts at path column
255
+ TMemoryPool suffixMemoryOwner ( 256 ) ;
256
+ TConstArrayRef<TConversionTypeInfo > suffixTypes (KeyColumnTypeInfos .data () + pathColPos, KeyColumnTypeInfos .size () - pathColPos); // starts at path column
445
257
bool suffixParsedOk = CellsFromTuple (&Request->Getstart_after_key_suffix ().Gettype (), Request->Getstart_after_key_suffix ().Getvalue (),
446
- suffixTypes, true , suffixCells, errStr, suffixMemoryOwner);
258
+ suffixTypes, true , false , suffixCells, errStr, suffixMemoryOwner);
447
259
if (!suffixParsedOk) {
448
260
ReplyWithError (Ydb::StatusIds::BAD_REQUEST,
449
261
" Invalid StartAfterKeySuffix: " + errStr, ctx);
@@ -506,7 +318,7 @@ class TObjectStorageListingRequestGrpc : public TActorBootstrapped<TObjectStorag
506
318
return false ;
507
319
}
508
320
509
- TVector<NScheme::TTypeInfo > types;
321
+ TVector<TConversionTypeInfo > types;
510
322
511
323
for (int i = 0 ; i < columnNames.items_size (); i++) {
512
324
const auto & colNameValue = columnNames.get_idx_items (i);
@@ -523,7 +335,7 @@ class TObjectStorageListingRequestGrpc : public TActorBootstrapped<TObjectStorag
523
335
const auto & columnInfo = entry.Columns [colIdIt->second ];
524
336
const auto & type = columnInfo.PType ;
525
337
526
- types.push_back (type);
338
+ types.emplace_back (type, columnInfo. PTypeMod , columnInfo. IsNotNullColumn );
527
339
528
340
const auto [it, inserted] = columnToRequestIndex.try_emplace (colName, columnToRequestIndex.size ());
529
341
@@ -552,14 +364,14 @@ class TObjectStorageListingRequestGrpc : public TActorBootstrapped<TObjectStorag
552
364
Filter.MatchTypes .push_back (dsMatchType);
553
365
}
554
366
555
- TConstArrayRef<NScheme::TTypeInfo > typesRef (types.data (), types.size ());
367
+ TConstArrayRef<TConversionTypeInfo > typesRef (types.data (), types.size ());
556
368
557
369
TVector<TCell> cells;
558
- TVector<TString> owner;
370
+ TMemoryPool owner ( 256 ) ;
559
371
560
372
TString err;
561
373
562
- bool filterParsedOk = CellsFromTuple (&filterType, columnValues, typesRef, true , cells, err, owner);
374
+ bool filterParsedOk = CellsFromTuple (&filterType, columnValues, typesRef, true , false , cells, err, owner);
563
375
564
376
if (!filterParsedOk) {
565
377
ReplyWithError (Ydb::StatusIds::BAD_REQUEST, Sprintf (" Invalid filter: '%s'" , err.data ()), ctx);
0 commit comments