Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/ROOT/RSqliteDS.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Author: Jakob Blomer CERN  07/2018
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
0005  * All rights reserved.                                                  *
0006  *                                                                       *
0007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0009  *************************************************************************/
0010 
0011 #ifndef ROOT_RSQLITEDS
0012 #define ROOT_RSQLITEDS
0013 
0014 #include "ROOT/RDataFrame.hxx"
0015 #include "ROOT/RDataSource.hxx"
0016 #include <string_view>
0017 
0018 #include <memory>
0019 #include <string>
0020 #include <vector>
0021 
0022 namespace ROOT::Internal::RDF {
0023 class R__CLING_PTRCHECK(off) RSqliteDSColumnReader final : public ROOT::Detail::RDF::RColumnReaderBase {
0024    void *fValuePtr;
0025    void *GetImpl(Long64_t) final { return fValuePtr; }
0026 
0027 public:
0028    RSqliteDSColumnReader(void *valuePtr) : fValuePtr(valuePtr) {}
0029 };
0030 } // namespace ROOT::Internal::RDF
0031 
0032 namespace ROOT {
0033 
0034 namespace RDF {
0035 
0036 namespace Internal {
0037 // Members are defined in RSqliteDS.cxx in order to not pullute this header file with sqlite3.h
0038 struct RSqliteDSDataSet;
0039 }
0040 
0041 // clang-format off
0042 /**
0043 \class ROOT::RDF::RSqliteDS
0044 \ingroup dataframe
0045 \brief RSqliteDS is an RDF data source implementation for SQL result sets from sqlite3 files.
0046 
0047 The RSqliteDS is able to feed an RDataFrame with data from a SQlite SELECT query. One can use it like
0048 
0049     auto rdf = ROOT::RDF::FromSqlite("/path/to/file.sqlite", "select name from table");
0050     auto h = rdf.Define("lName", "name.length()").Histo1D("lName");
0051 
0052 The data source has to provide column types for all the columns. Determining column types in SQlite is tricky
0053 as it is dynamically typed and in principle each row can have different column types. The following heuristics
0054 is used:
0055 
0056   - If a table column is queried as is ("SELECT colname FROM table"), the default/declared column type is taken.
0057   - For expressions ("SELECT 1+1 FROM table"), the type of the first row of the result set determines the column type.
0058     That can result in a column to be of thought of type NULL where subsequent rows actually have meaningful values.
0059     The provided SELECT query can be used to avoid such ambiguities.
0060 */
0061 class RSqliteDS final : public ROOT::RDF::RDataSource {
0062 private:
0063    // clang-format off
0064    /// All the types known to SQlite. Changes require changing fgTypeNames, too.
0065    enum class ETypes {
0066       kInteger,
0067       kReal,
0068       kText,
0069       kBlob,
0070       kNull
0071    };
0072    // clang-format on
0073 
0074    /// Used to hold a single "cell" of the SELECT query's result table. Can be changed to std::variant once available.
0075    struct Value_t {
0076       explicit Value_t(ETypes type);
0077 
0078       ETypes fType;
0079       bool fIsActive; ///< Not all columns of the query are necessarily used by the RDF. Allows for skipping them.
0080       Long64_t fInteger;
0081       double fReal;
0082       std::string fText;
0083       std::vector<unsigned char> fBlob;
0084       void *fNull;
0085       void *fPtr; ///< Points to one of the values; an address to this pointer is returned by GetColumnReadersImpl.
0086    };
0087 
0088    void SqliteError(int errcode);
0089 
0090    std::unique_ptr<Internal::RSqliteDSDataSet> fDataSet;
0091    ULong64_t fNRow;
0092    std::vector<std::string> fColumnNames;
0093    std::vector<ETypes> fColumnTypes;
0094    /// The data source is inherently single-threaded and returns only one row at a time. This vector holds the results.
0095    std::vector<Value_t> fValues;
0096 
0097    // clang-format off
0098    /// Corresponds to the types defined in ETypes.
0099    static constexpr char const *fgTypeNames[] = {
0100       "Long64_t",
0101       "double",
0102       "std::string",
0103       "std::vector<unsigned char>",
0104       "void *"
0105    };
0106    // clang-format on
0107 
0108 public:
0109    RSqliteDS(const std::string &fileName, const std::string &query);
0110    // Rule of five
0111    RSqliteDS(const RSqliteDS &) = delete;
0112    RSqliteDS &operator=(const RSqliteDS &) = delete;
0113    RSqliteDS(RSqliteDS &&) = delete;
0114    RSqliteDS &operator=(RSqliteDS &&) = delete;
0115    ~RSqliteDS() final;
0116 
0117    void SetNSlots(unsigned int nSlots) final;
0118    const std::vector<std::string> &GetColumnNames() const final;
0119    bool HasColumn(std::string_view colName) const final;
0120    std::string GetTypeName(std::string_view colName) const final;
0121    std::vector<std::pair<ULong64_t, ULong64_t>> GetEntryRanges() final;
0122    bool SetEntry(unsigned int slot, ULong64_t entry) final;
0123    void Initialize() final;
0124    std::string GetLabel() final;
0125 
0126    std::unique_ptr<ROOT::Detail::RDF::RColumnReaderBase>
0127    GetColumnReaders(unsigned int slot, std::string_view colName, const std::type_info &tid) final;
0128 
0129 protected:
0130    Record_t GetColumnReadersImpl(std::string_view name, const std::type_info &) final;
0131 };
0132 
0133 RDataFrame FromSqlite(std::string_view fileName, std::string_view query);
0134 
0135 } // namespace RDF
0136 
0137 } // namespace ROOT
0138 
0139 #endif