diff --git a/tree/dataframe/src/RSqliteDS.cxx b/tree/dataframe/src/RSqliteDS.cxx index d598320ca2a0ce8c12b524b23263f3624f37dceb..2fdec3f72790eb7a81fabd01ba3af4cd042581b7 100644 --- a/tree/dataframe/src/RSqliteDS.cxx +++ b/tree/dataframe/src/RSqliteDS.cxx @@ -195,8 +195,8 @@ void RSqliteDS::Initialise() { RDataFrame MakeSqliteDataFrame(std::string_view fileName, std::string_view query) { - ROOT::RDataFrame tdf(std::make_unique<RSqliteDS>(fileName, query)); - return tdf; + ROOT::RDataFrame rdf(std::make_unique<RSqliteDS>(fileName, query)); + return rdf; } diff --git a/tree/dataframe/test/CMakeLists.txt b/tree/dataframe/test/CMakeLists.txt index 59e5a43af5a29ad3ccd6ce18b199ce6ac3ce74b3..ad8db8d4f05718cf9d23cd94fca831d92537f6f2 100644 --- a/tree/dataframe/test/CMakeLists.txt +++ b/tree/dataframe/test/CMakeLists.txt @@ -27,6 +27,11 @@ if(ARROW_FOUND) ROOT_ADD_GTEST(datasource_arrow datasource_arrow.cxx LIBRARIES ROOTDataFrame ${ARROW_SHARED_LIB}) target_include_directories(datasource_arrow BEFORE PRIVATE ${ARROW_INCLUDE_DIR}) endif() +if(sqlite) + configure_file(RSqliteDS_test.sqlite . COPYONLY) + ROOT_ADD_GTEST(datasource_sqlite datasource_sqlite.cxx LIBRARIES ROOTDataFrame ${SQLITE_LIBRARIES}) + target_include_directories(datasource_sqlite BEFORE PRIVATE ${SQLITE_INCLUDE_DIR}) +endif() ROOT_ADD_GTEST(datasource_csv datasource_csv.cxx LIBRARIES ROOTDataFrame) ROOT_ADD_GTEST(datasource_lazy datasource_lazy.cxx LIBRARIES ROOTDataFrame) diff --git a/tree/dataframe/test/RSqliteDS_test.sqlite b/tree/dataframe/test/RSqliteDS_test.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..eb3758545387d7b3f7deab7ee7adfc9ede1c0264 Binary files /dev/null and b/tree/dataframe/test/RSqliteDS_test.sqlite differ diff --git a/tree/dataframe/test/datasource_sqlite.cxx b/tree/dataframe/test/datasource_sqlite.cxx new file mode 100644 index 0000000000000000000000000000000000000000..99c5c71b3874f7d707123c361982fbe7baaa11c7 --- /dev/null +++ b/tree/dataframe/test/datasource_sqlite.cxx @@ -0,0 +1,172 @@ +#include <ROOT/RDataFrame.hxx> +#include <ROOT/RMakeUnique.hxx> +#include <ROOT/RSqliteDS.hxx> +#include <ROOT/TSeq.hxx> + +#include <gtest/gtest.h> + +#include <algorithm> +#include <memory> + +using namespace ROOT::RDF; + +auto fileName0 = "RSqliteDS_test.sqlite"; +auto query0 = "SELECT * FROM test"; +auto query1 = "SELECT fint + 1, freal/1.0 as fmyreal, NULL, 'X', fblob FROM test"; + + +TEST(RSqliteDS, Basics) +{ + auto rdf = std::make_unique<ROOT::RDataFrame>(MakeSqliteDataFrame(fileName0, query0)); + ASSERT_TRUE(rdf); + EXPECT_EQ(1, *(rdf->Min("fint"))); + EXPECT_EQ(2, *(rdf->Max("fint"))); + + EXPECT_THROW(MakeSqliteDataFrame(fileName0, ""), std::runtime_error); + EXPECT_THROW(MakeSqliteDataFrame("", query0), std::runtime_error); +} + + +TEST(RSqliteDS, ColTypeNames) +{ + RSqliteDS rds(fileName0, query0); + + auto colNames = rds.GetColumnNames(); + ASSERT_EQ(5U, colNames.size()); + std::sort(colNames.begin(), colNames.end()); + EXPECT_EQ("fblob", colNames[0]); + EXPECT_EQ("fint", colNames[1]); + EXPECT_EQ("fnull", colNames[2]); + EXPECT_EQ("freal", colNames[3]); + EXPECT_EQ("ftext", colNames[4]); + + EXPECT_TRUE(rds.HasColumn("fint")); + EXPECT_TRUE(rds.HasColumn("freal")); + EXPECT_TRUE(rds.HasColumn("ftext")); + EXPECT_TRUE(rds.HasColumn("fblob")); + EXPECT_TRUE(rds.HasColumn("fnull")); + EXPECT_FALSE(rds.HasColumn("foo")); + + EXPECT_EQ("Long64_t", rds.GetTypeName("fint")); + EXPECT_EQ("double", rds.GetTypeName("freal")); + EXPECT_EQ("std::string", rds.GetTypeName("ftext")); + EXPECT_EQ("std::vector<unsigned char>", rds.GetTypeName("fblob")); + EXPECT_EQ("void *", rds.GetTypeName("fnull")); + EXPECT_THROW(rds.GetTypeName("foo"), std::runtime_error); +} + + +TEST(RSqliteDS, ExprTypeNames) +{ + RSqliteDS rds(fileName0, query1); + + EXPECT_EQ("Long64_t", rds.GetTypeName("fint + 1")); + EXPECT_EQ("double", rds.GetTypeName("fmyreal")); + EXPECT_EQ("void *", rds.GetTypeName("NULL")); + EXPECT_EQ("std::string", rds.GetTypeName("'X'")); + EXPECT_EQ("std::vector<unsigned char>", rds.GetTypeName("fblob")); + EXPECT_THROW(rds.GetTypeName("foo"), std::runtime_error); +} + + +TEST(RSqliteDS, ColumnReaders) +{ + RSqliteDS rds(fileName0, query0); + const auto nSlots = 2U; + rds.SetNSlots(nSlots); + auto vals = rds.GetColumnReaders<Long64_t>("fint"); + rds.Initialise(); + auto ranges = rds.GetEntryRanges(); + EXPECT_EQ(1U, ranges.size()); + for (auto i : ROOT::TSeq<unsigned>(0, nSlots)) { + EXPECT_TRUE(rds.SetEntry(i, ranges[0].first)); + auto val = **vals[i]; + EXPECT_EQ(1, val); + } + + EXPECT_THROW(rds.GetColumnReaders<double>("fint"), std::runtime_error); +} + + +TEST(RSqliteDS, GetEntryRanges) +{ + RSqliteDS rds(fileName0, query0); + rds.Initialise(); + auto ranges = rds.GetEntryRanges(); + ASSERT_EQ(1U, ranges.size()); + EXPECT_EQ(0U, ranges[0].first); + EXPECT_EQ(1U, ranges[0].second); + ranges = rds.GetEntryRanges(); + ASSERT_EQ(1U, ranges.size()); + EXPECT_EQ(1U, ranges[0].first); + EXPECT_EQ(2U, ranges[0].second); + ranges = rds.GetEntryRanges(); + EXPECT_EQ(0U, ranges.size()); + + // New event loop + rds.Initialise(); + ranges = rds.GetEntryRanges(); + EXPECT_EQ(1U, ranges.size()); + EXPECT_EQ(0U, ranges[0].first); + EXPECT_EQ(1U, ranges[0].second); +} + + +TEST(RSqliteDS, SetEntry) +{ + const float epsilon = 0.001; + RSqliteDS rds(fileName0, query0); + auto vint = rds.GetColumnReaders<Long64_t>("fint"); + auto vreal = rds.GetColumnReaders<double>("freal"); + auto vtext = rds.GetColumnReaders<std::string>("ftext"); + auto vblob = rds.GetColumnReaders<std::vector<unsigned char>>("fblob"); + auto vnull = rds.GetColumnReaders<void *>("fnull"); + + rds.Initialise(); + + rds.GetEntryRanges(); + EXPECT_TRUE(rds.SetEntry(0, 0)); + EXPECT_EQ(1, **vint[0]); + EXPECT_NEAR(1.0, **vreal[0], epsilon); + EXPECT_EQ("1", **vtext[0]); + EXPECT_EQ(1U, (**vblob[0]).size()); + EXPECT_EQ('1', (**vblob[0])[0]); + EXPECT_EQ(nullptr, **vnull[0]); + + rds.GetEntryRanges(); + EXPECT_TRUE(rds.SetEntry(0, 1)); + EXPECT_EQ(2, **vint[0]); + EXPECT_NEAR(2.0, **vreal[0], epsilon); + EXPECT_EQ("2", **vtext[0]); + EXPECT_EQ(1U, (**vblob[0]).size()); + EXPECT_EQ('2', (**vblob[0])[0]); + EXPECT_EQ(nullptr, **vnull[0]); +} + + +#ifdef R__USE_IMT + +TEST(RSqliteDS, IMT) +{ + using Blob_t = std::vector<unsigned char>; + const float epsilon = 0.001; + const auto nSlots = 4U; + ROOT::EnableImplicitMT(nSlots); + + auto rdf = std::make_unique<ROOT::RDataFrame>(MakeSqliteDataFrame(fileName0, query0)); + ASSERT_TRUE(rdf); + EXPECT_EQ(3, *(rdf->Sum("fint"))); + EXPECT_NEAR(3.0, *(rdf->Sum("freal")), epsilon); + auto sum_text = *(rdf->Reduce([](std::string a, std::string b) {return a+b;}, "ftext")); + std::sort(sum_text.begin(), sum_text.end()); + EXPECT_EQ("12", sum_text); + auto sum_blob = *(rdf->Reduce( + [](Blob_t a, Blob_t b) {a.insert(a.end(), b.begin(), b.end()); return a;}, + "fblob")); + std::sort(sum_blob.begin(), sum_blob.end()); + ASSERT_EQ(2U, sum_blob.size()); + EXPECT_EQ('1', sum_blob[0]); + EXPECT_EQ('2', sum_blob[1]); +} + +#endif // R__USE_IMT