@@ -46,7 +46,7 @@ class TCsvToYdbConverter {
46
46
}
47
47
return static_cast <T>(value);
48
48
} catch (std::exception& e) {
49
- throw TMisuseException () << " Expected " << Parser.GetPrimitive () << " value, recieved: \" " << token << " \" ." ;
49
+ throw TCsvParseException () << " Expected " << Parser.GetPrimitive () << " value, recieved: \" " << token << " \" ." ;
50
50
}
51
51
}
52
52
@@ -173,7 +173,7 @@ class TCsvToYdbConverter {
173
173
Builder.TzTimestamp (token);
174
174
break ;
175
175
default :
176
- throw TMisuseException () << " Unsupported primitive type: " << Parser.GetPrimitive ();
176
+ throw TCsvParseException () << " Unsupported primitive type: " << Parser.GetPrimitive ();
177
177
}
178
178
}
179
179
@@ -224,7 +224,7 @@ class TCsvToYdbConverter {
224
224
break ;
225
225
}
226
226
default :
227
- throw TMisuseException () << " Unsupported type kind: " << Parser.GetKind ();
227
+ throw TCsvParseException () << " Unsupported type kind: " << Parser.GetKind ();
228
228
}
229
229
}
230
230
@@ -259,7 +259,7 @@ class TCsvToYdbConverter {
259
259
break ;
260
260
261
261
default :
262
- throw TMisuseException () << " Unsupported type kind: " << Parser.GetKind ();
262
+ throw TCsvParseException () << " Unsupported type kind: " << Parser.GetKind ();
263
263
}
264
264
}
265
265
@@ -276,15 +276,15 @@ class TCsvToYdbConverter {
276
276
if (token == " false" ) {
277
277
return false ;
278
278
}
279
- throw TMisuseException () << " Expected bool value: \" true\" or \" false\" , recieved: \" " << token << " \" ." ;
279
+ throw TCsvParseException () << " Expected bool value: \" true\" or \" false\" , recieved: \" " << token << " \" ." ;
280
280
}
281
281
282
282
void EnsureNull (TStringBuf token) const {
283
283
if (!NullValue) {
284
- throw TMisuseException () << " Expected null value instead of \" " << token << " \" , but null value is not set." ;
284
+ throw TCsvParseException () << " Expected null value instead of \" " << token << " \" , but null value is not set." ;
285
285
}
286
286
if (token != NullValue) {
287
- throw TMisuseException () << " Expected null value: \" " << NullValue << " \" , recieved: \" " << token << " \" ." ;
287
+ throw TCsvParseException () << " Expected null value: \" " << NullValue << " \" , recieved: \" " << token << " \" ." ;
288
288
}
289
289
}
290
290
@@ -299,6 +299,46 @@ class TCsvToYdbConverter {
299
299
TValueBuilder Builder;
300
300
};
301
301
302
+ TCsvParseException FormatError (const std::exception& inputError,
303
+ const TCsvParser::TParseMetadata& meta,
304
+ std::optional<TString> columnName = {}) {
305
+ auto outputError = TCsvParseException () << " Error during CSV parsing" ;
306
+ if (meta.Line .has_value ()) {
307
+ outputError << " in line " << meta.Line .value ();
308
+ }
309
+ if (columnName.has_value ()) {
310
+ outputError << " in column `" << columnName.value () << " `" ;
311
+ }
312
+ if (meta.Filename .has_value ()) {
313
+ outputError << " in file `" << meta.Filename .value () << " `" ;
314
+ }
315
+ outputError << " :\n " << inputError.what ();
316
+ return outputError;
317
+ }
318
+
319
+ TValue FieldToValue (TTypeParser& parser,
320
+ TStringBuf token,
321
+ const std::optional<TString>& nullValue,
322
+ const TCsvParser::TParseMetadata& meta,
323
+ TString columnName) {
324
+ try {
325
+ TCsvToYdbConverter converter (parser, nullValue);
326
+ return converter.Convert (token);
327
+ } catch (std::exception& e) {
328
+ throw FormatError (e, meta, columnName);
329
+ }
330
+ }
331
+
332
+ TStringBuf Consume (NCsvFormat::CsvSplitter& splitter,
333
+ const TCsvParser::TParseMetadata& meta,
334
+ TString columnName) {
335
+ try {
336
+ return splitter.Consume ();
337
+ } catch (std::exception& e) {
338
+ throw FormatError (e, meta, columnName);
339
+ }
340
+ }
341
+
302
342
}
303
343
304
344
TCsvParser::TCsvParser (TString&& headerRow, const char delimeter, const std::optional<TString>& nullValue,
@@ -325,19 +365,14 @@ TCsvParser::TCsvParser(TVector<TString>&& header, const char delimeter, const st
325
365
{
326
366
}
327
367
328
- TValue TCsvParser::FieldToValue (TTypeParser& parser, TStringBuf token) const {
329
- TCsvToYdbConverter converter (parser, NullValue);
330
- return converter.Convert (token);
331
- }
332
-
333
- void TCsvParser::GetParams (TString&& data, TParamsBuilder& builder) const {
368
+ void TCsvParser::GetParams (TString&& data, TParamsBuilder& builder, const TParseMetadata& meta) const {
334
369
NCsvFormat::CsvSplitter splitter (data, Delimeter);
335
370
auto headerIt = Header.begin ();
336
371
do {
337
- TStringBuf token = splitter.Consume ();
338
372
if (headerIt == Header.end ()) {
339
- throw TMisuseException ( ) << " Header contains less fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " ;
373
+ throw FormatError ( yexception ( ) << " Header contains less fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " , meta) ;
340
374
}
375
+ TStringBuf token = Consume (splitter, meta, *headerIt);
341
376
TString fullname = " $" + *headerIt;
342
377
auto paramIt = ParamTypes->find (fullname);
343
378
if (paramIt == ParamTypes->end ()) {
@@ -347,35 +382,36 @@ void TCsvParser::GetParams(TString&& data, TParamsBuilder& builder) const {
347
382
if (ParamSources) {
348
383
auto paramSource = ParamSources->find (fullname);
349
384
if (paramSource != ParamSources->end ()) {
350
- throw TMisuseException ( ) << " Parameter " << fullname << " value found in more than one source: stdin, " << paramSource->second << " ." ;
385
+ throw FormatError ( yexception ( ) << " Parameter " << fullname << " value found in more than one source: stdin, " << paramSource->second << " ." , meta) ;
351
386
}
352
387
}
353
388
TTypeParser parser (paramIt->second );
354
- builder.AddParam (fullname, FieldToValue (parser, token));
389
+ builder.AddParam (fullname, FieldToValue (parser, token, NullValue, meta, *headerIt ));
355
390
++headerIt;
356
391
} while (splitter.Step ());
357
392
358
393
if (headerIt != Header.end ()) {
359
- throw TMisuseException ( ) << " Header contains more fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " ;
394
+ throw FormatError ( yexception ( ) << " Header contains more fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " , meta) ;
360
395
}
361
396
}
362
397
363
- void TCsvParser::GetValue (TString&& data, TValueBuilder& builder, const TType& type) const {
398
+ void TCsvParser::GetValue (TString&& data, TValueBuilder& builder, const TType& type, const TParseMetadata& meta ) const {
364
399
NCsvFormat::CsvSplitter splitter (data, Delimeter);
365
400
auto headerIt = Header.cbegin ();
366
401
std::map<TString, TStringBuf> fields;
367
402
do {
368
- TStringBuf token = splitter.Consume ();
369
403
if (headerIt == Header.cend ()) {
370
- throw TMisuseException ( ) << " Header contains less fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " ;
404
+ throw FormatError ( yexception ( ) << " Header contains less fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " , meta) ;
371
405
}
406
+ TStringBuf token = Consume (splitter, meta, *headerIt);
372
407
fields[*headerIt] = token;
373
408
++headerIt;
374
409
} while (splitter.Step ());
375
410
376
411
if (headerIt != Header.cend ()) {
377
- throw TMisuseException ( ) << " Header contains more fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " ;
412
+ throw FormatError ( yexception ( ) << " Header contains more fields than data. Header: \" " << HeaderRow << " \" , data: \" " << data << " \" " , meta) ;
378
413
}
414
+
379
415
builder.BeginStruct ();
380
416
TTypeParser parser (type);
381
417
parser.OpenStruct ();
@@ -386,10 +422,11 @@ void TCsvParser::GetValue(TString&& data, TValueBuilder& builder, const TType& t
386
422
}
387
423
auto fieldIt = fields.find (name);
388
424
if (fieldIt == fields.end ()) {
389
- throw TMisuseException ( ) << " No member \" " << name << " \" in csv string for YDB struct type" ;
425
+ throw FormatError ( yexception ( ) << " No member \" " << name << " \" in csv string for YDB struct type" , meta) ;
390
426
}
391
- builder.AddMember (name, FieldToValue (parser, fieldIt->second ));
427
+ builder.AddMember (name, FieldToValue (parser, fieldIt->second , NullValue, meta, name ));
392
428
}
429
+
393
430
parser.CloseStruct ();
394
431
builder.EndStruct ();
395
432
}
0 commit comments