@@ -46,7 +46,7 @@ class TCsvToYdbConverter {
4646 }
4747 return static_cast <T>(value);
4848 } catch (std::exception& e) {
49- throw TMisuseException () << " Expected " << Parser.GetPrimitive () << " value, recieved: \" " << token << " \" ." ;
49+ throw TCsvParseException () << " Expected " << Parser.GetPrimitive () << " value, recieved: \" " << token << " \" ." ;
5050 }
5151 }
5252
@@ -173,7 +173,7 @@ class TCsvToYdbConverter {
173173 Builder.TzTimestamp (token);
174174 break ;
175175 default :
176- throw TMisuseException () << " Unsupported primitive type: " << Parser.GetPrimitive ();
176+ throw TCsvParseException () << " Unsupported primitive type: " << Parser.GetPrimitive ();
177177 }
178178 }
179179
@@ -224,7 +224,7 @@ class TCsvToYdbConverter {
224224 break ;
225225 }
226226 default :
227- throw TMisuseException () << " Unsupported type kind: " << Parser.GetKind ();
227+ throw TCsvParseException () << " Unsupported type kind: " << Parser.GetKind ();
228228 }
229229 }
230230
@@ -259,7 +259,7 @@ class TCsvToYdbConverter {
259259 break ;
260260
261261 default :
262- throw TMisuseException () << " Unsupported type kind: " << Parser.GetKind ();
262+ throw TCsvParseException () << " Unsupported type kind: " << Parser.GetKind ();
263263 }
264264 }
265265
@@ -276,15 +276,15 @@ class TCsvToYdbConverter {
276276 if (token == " false" ) {
277277 return false ;
278278 }
279- throw TMisuseException () << " Expected bool value: \" true\" or \" false\" , recieved: \" " << token << " \" ." ;
279+ throw TCsvParseException () << " Expected bool value: \" true\" or \" false\" , recieved: \" " << token << " \" ." ;
280280 }
281281
282282 void EnsureNull (TStringBuf token) const {
283283 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." ;
285285 }
286286 if (token != NullValue) {
287- throw TMisuseException () << " Expected null value: \" " << NullValue << " \" , recieved: \" " << token << " \" ." ;
287+ throw TCsvParseException () << " Expected null value: \" " << NullValue << " \" , recieved: \" " << token << " \" ." ;
288288 }
289289 }
290290
@@ -299,6 +299,46 @@ class TCsvToYdbConverter {
299299 TValueBuilder Builder;
300300};
301301
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+
302342}
303343
304344TCsvParser::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
325365{
326366}
327367
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 {
334369 NCsvFormat::CsvSplitter splitter (data, Delimeter);
335370 auto headerIt = Header.begin ();
336371 do {
337- TStringBuf token = splitter.Consume ();
338372 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) ;
340374 }
375+ TStringBuf token = Consume (splitter, meta, *headerIt);
341376 TString fullname = " $" + *headerIt;
342377 auto paramIt = ParamTypes->find (fullname);
343378 if (paramIt == ParamTypes->end ()) {
@@ -347,35 +382,36 @@ void TCsvParser::GetParams(TString&& data, TParamsBuilder& builder) const {
347382 if (ParamSources) {
348383 auto paramSource = ParamSources->find (fullname);
349384 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) ;
351386 }
352387 }
353388 TTypeParser parser (paramIt->second );
354- builder.AddParam (fullname, FieldToValue (parser, token));
389+ builder.AddParam (fullname, FieldToValue (parser, token, NullValue, meta, *headerIt ));
355390 ++headerIt;
356391 } while (splitter.Step ());
357392
358393 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) ;
360395 }
361396}
362397
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 {
364399 NCsvFormat::CsvSplitter splitter (data, Delimeter);
365400 auto headerIt = Header.cbegin ();
366401 std::map<TString, TStringBuf> fields;
367402 do {
368- TStringBuf token = splitter.Consume ();
369403 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) ;
371405 }
406+ TStringBuf token = Consume (splitter, meta, *headerIt);
372407 fields[*headerIt] = token;
373408 ++headerIt;
374409 } while (splitter.Step ());
375410
376411 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) ;
378413 }
414+
379415 builder.BeginStruct ();
380416 TTypeParser parser (type);
381417 parser.OpenStruct ();
@@ -386,10 +422,11 @@ void TCsvParser::GetValue(TString&& data, TValueBuilder& builder, const TType& t
386422 }
387423 auto fieldIt = fields.find (name);
388424 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) ;
390426 }
391- builder.AddMember (name, FieldToValue (parser, fieldIt->second ));
427+ builder.AddMember (name, FieldToValue (parser, fieldIt->second , NullValue, meta, name ));
392428 }
429+
393430 parser.CloseStruct ();
394431 builder.EndStruct ();
395432}
0 commit comments