@@ -1149,13 +1149,15 @@ private:
11491149 typename std::enable_if<!TDFInternal::TNeedJitting<BranchTypes...>::value, int >::type = 0 >
11501150 TResultProxy<ActionResultType> CreateAction (const ColumnNames_t &columns, const std::shared_ptr<ActionResultType> &r)
11511151 {
1152- auto loopManager = GetDataFrameChecked ();
1153- const auto nColumns = sizeof ...(BranchTypes);
1154- const auto validColumnNames = GetValidatedColumnNames (*loopManager, nColumns, columns);
1152+ auto lm = GetDataFrameChecked ();
1153+ constexpr auto nColumns = sizeof ...(BranchTypes);
1154+ const auto colsAndUndefCols = CheckColumnNames (columns, nColumns, *lm);
1155+ if (fDataSource )
1156+ DefineDataSourceColumns<BranchTypes...>(colsAndUndefCols, *lm, TDFInternal::GenStaticSeq_t<nColumns>());
1157+ const auto &theColumnNames = colsAndUndefCols.first ;
11551158 const auto nSlots = fProxiedPtr ->GetNSlots ();
1156- TDFInternal::BuildAndBook<BranchTypes...>(validColumnNames, r, nSlots, *loopManager, *fProxiedPtr ,
1157- (ActionType *)nullptr );
1158- return MakeResultProxy (r, loopManager);
1159+ TDFInternal::BuildAndBook<BranchTypes...>(theColumnNames, r, nSlots, *lm, *fProxiedPtr , (ActionType *)nullptr );
1160+ return MakeResultProxy (r, lm);
11591161 }
11601162
11611163 // User did not specify type, do type inference
@@ -1238,12 +1240,18 @@ private:
12381240 return snapshotTDF;
12391241 }
12401242
1241- ColumnNames_t GetValidatedColumnNames (TLoopManager &lm, const unsigned int nColumns,
1242- const ColumnNames_t &userColumns)
1243+ // / Given the desired number of columns and the user-provided list of columns:
1244+ // / * fallback to using the first nColumns default columns if needed (or throw if nColumns > nDefaultColumns)
1245+ // / * check that selected column names refer to valid branches, custom columns or datasource columns (throw if not)
1246+ // / Return the list of selected column names and a bitmask indicating the columns that must be defined via datasource
1247+ std::pair<ColumnNames_t, std::vector<bool >>
1248+ CheckColumnNames (const ColumnNames_t &userColumns, const unsigned int nColumns, TLoopManager &lm)
12431249 {
12441250 const auto &defaultColumns = lm.GetDefaultColumnNames ();
1245- const auto trueColumns = TDFInternal::SelectColumns (nColumns, userColumns, defaultColumns);
1246- const auto unknownColumns = TDFInternal::FindUnknownColumns (trueColumns, lm.GetTree (), fValidCustomColumns );
1251+ const auto selectedColumns = TDFInternal::SelectColumns (nColumns, userColumns, defaultColumns);
1252+ const auto unknownColumns =
1253+ TDFInternal::FindUnknownColumns (selectedColumns, lm.GetTree (), fValidCustomColumns ,
1254+ fDataSource ? fDataSource ->GetColumnNames () : ColumnNames_t{});
12471255
12481256 if (!unknownColumns.empty ()) {
12491257 // throw
@@ -1256,7 +1264,54 @@ private:
12561264 throw std::runtime_error (" Unknown column" + unknowns.str ());
12571265 }
12581266
1259- return trueColumns;
1267+ const auto mustBeDefined = FindUndefinedDSColumns (selectedColumns, lm.GetDefinedDataSourceColumns ());
1268+ return std::make_pair (selectedColumns, mustBeDefined);
1269+ }
1270+
1271+ // TODO remove usages of this everywhere
1272+ ColumnNames_t
1273+ GetValidatedColumnNames (TLoopManager &lm, const unsigned int nColumns, const ColumnNames_t &userColumns) {
1274+ return CheckColumnNames (userColumns, nColumns, lm).first ;
1275+ }
1276+
1277+ // / Return a bitset each element of which indicates whether the corresponding element in `selectedColumns` is the
1278+ // / name of a column that must be defined via datasource. All elements of the returned vector are false if no
1279+ // / data-source is present.
1280+ std::vector<bool > FindUndefinedDSColumns (const ColumnNames_t &requestedCols, const ColumnNames_t &definedDSCols)
1281+ {
1282+ const auto nColumns = requestedCols.size ();
1283+ std::vector<bool > mustBeDefined (nColumns, false );
1284+ if (fDataSource ) {
1285+ for (auto i = 0u ; i < nColumns; ++i)
1286+ mustBeDefined[i] =
1287+ std::find (definedDSCols.begin (), definedDSCols.end (), requestedCols[i]) == definedDSCols.end ();
1288+ }
1289+ return mustBeDefined;
1290+ }
1291+
1292+ template <typename ... ColumnTypes, int ... S>
1293+ void DefineDataSourceColumns (const std::pair<std::vector<std::string>, std::vector<bool >> &colsAndUndefCols,
1294+ TLoopManager &lm, TDFInternal::StaticSeq<S...> /* dummy*/ )
1295+ {
1296+ assert (fDataSource != nullptr );
1297+ const auto &columns = colsAndUndefCols.first ;
1298+ const auto &mustBeDefined = colsAndUndefCols.second ;
1299+ if (std::none_of (mustBeDefined.begin (), mustBeDefined.end (), [](bool b) { return b; })) {
1300+ // no need to define any column
1301+ return ;
1302+ } else {
1303+ // hack to expand a template parameter pack without c++17 fold expressions.
1304+ std::initializer_list<int > expander{
1305+ (mustBeDefined[S] ? DefineDSColumnHelper<ColumnTypes>(columns[S], lm) : /* no-op*/ ((void )0 ), 0 )...};
1306+ }
1307+ }
1308+
1309+ template <typename T>
1310+ void DefineDSColumnHelper (std::string_view name, TLoopManager &lm) {
1311+ const auto nSlots = fProxiedPtr ->GetNSlots ();
1312+ auto readers = fDataSource ->GetColumnReaders <T>(name, nSlots);
1313+ DefineSlot (name, [readers](unsigned int slot) { return **readers[slot]; });
1314+ lm.AddDataSourceColumn (name);
12601315 }
12611316
12621317protected:
0 commit comments