diff --git a/src/FSharp.Data.DesignTime/Csv/CsvProvider.fs b/src/FSharp.Data.DesignTime/Csv/CsvProvider.fs index 9ac15ef05..4c2d50c40 100644 --- a/src/FSharp.Data.DesignTime/Csv/CsvProvider.fs +++ b/src/FSharp.Data.DesignTime/Csv/CsvProvider.fs @@ -202,10 +202,12 @@ type public CsvProvider(cfg: TypeProviderConfig) as this = CreateFromTextReaderForSampleList = fun _ -> failwith "Not Applicable" CreateFromValue = None } - let maxNumberOfRows = if inferRows > 0 then Some inferRows else None - // On the CsvProvider the schema might be partial and we will still infer from the sample - // So we handle it in a custom way + // So we handle it in a custom way. + // Note: we pass None for maxNumberOfRows so that the raw text is never truncated by + // line count. Truncating by line is incorrect for CSV because a single data row can span + // multiple text lines when fields are quoted (see issue #1439). Row limiting during + // inference is handled correctly by InferColumnTypes via its own inferRows parameter. generateType "CSV" (if sample <> "" then Sample sample else Schema schema) @@ -216,7 +218,7 @@ type public CsvProvider(cfg: TypeProviderConfig) as this = resolutionFolder resource typeName - maxNumberOfRows + None // Add static parameter that specifies the API we want to get (compile-time) let parameters = diff --git a/tests/FSharp.Data.Tests/CsvProvider.fs b/tests/FSharp.Data.Tests/CsvProvider.fs index 6827f13c3..7bcc9b207 100644 --- a/tests/FSharp.Data.Tests/CsvProvider.fs +++ b/tests/FSharp.Data.Tests/CsvProvider.fs @@ -705,3 +705,18 @@ let ``Can infer from a multiline schema`` () = csv.NumberOfColumns |> should equal 16 firstRow.OrderCreated |> should equal "2022-01-01 10:00:00" firstRow.FioFull |> should equal "John Smith" + +// Regression test for issue #1439: InferRows must count CSV rows, not text lines. +// A multiline quoted field occupies 2 text lines but is only 1 data row. +// With InferRows=2, both data rows should be accessible (the first spans 2 lines). +type MultilineFieldsCsv = CsvProvider<"Data/MultilineFields.csv", InferRows=2> + +[] +let ``InferRows counts CSV rows not text lines for multiline quoted fields`` () = + let csv = MultilineFieldsCsv.GetSample() + let rows = csv.Rows |> Seq.toArray + rows.Length |> should equal 2 + rows.[0].F1 |> should equal "multi-\nline field" + rows.[0].F2 |> should equal 2 + rows.[1].F1 |> should equal "normal" + rows.[1].F2 |> should equal 3 diff --git a/tests/FSharp.Data.Tests/Data/MultilineFields.csv b/tests/FSharp.Data.Tests/Data/MultilineFields.csv new file mode 100644 index 000000000..ff3d10653 --- /dev/null +++ b/tests/FSharp.Data.Tests/Data/MultilineFields.csv @@ -0,0 +1,4 @@ +f1,f2 +"multi- +line field",2 +normal,3