- Timestamp:
- 05/26/20 20:20:25 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/rootifysql.cc
r19802 r19966 9 9 #include "Time.h" 10 10 #include "Splitting.h" 11 #include "FileEntry.h" 11 12 12 13 #include <TROOT.h> … … 55 56 ("compression,c", var<uint16_t>(1), "zlib compression level for the root file") 56 57 ("tree,t", var<string>("Result"), "Name of the root tree") 58 ("accurate", po_switch(), "Accurate type conversion, otherwise all branches are creates as double which is often more convenient.") 57 59 ("ignore", vars<string>(), "Ignore the given columns") 58 60 ("null,n", po_switch(), "Redirect the root output file to /dev/null (mainly for debugging purposes, e.g. performance studies)") … … 464 466 } 465 467 468 template<typename T> 469 void Convert(FileEntry::Container &container, const mysqlpp::String &col) 470 { 471 *reinterpret_cast<T*>(container.ptr) = static_cast<T>(col); 472 } 473 474 466 475 int main(int argc, const char* argv[]) 467 476 { … … 491 500 const bool explain = conf.Get<bool>("explain"); 492 501 const bool profiling = conf.Get<bool>("profiling"); 502 const bool accurate = conf.Get<bool>("accurate"); 493 503 const uint16_t verbose = conf.Get<uint16_t>("verbose"); 494 504 const uint16_t compression = conf.Get<uint16_t>("compression"); … … 810 820 const mysqlpp::FieldNames &l = *row.field_list().list; 811 821 812 vector<double> buf(l.size()); 813 vector<uint8_t> typ(l.size(),'n'); // n=number [double], d is used for DateTime 822 vector<FileEntry::Container> container; 814 823 815 824 UInt_t cols = 0; … … 834 843 ttree.emplace_back(new TTree((tree+"["+to_string(i)+"]").c_str(), query.c_str())); 835 844 845 size_t skipno = 0; 836 846 size_t skipat = 0; 837 847 size_t skipreg = 0; 848 size_t skipch = 0; 838 849 for (size_t i=0; i<l.size(); i++) 839 850 { 840 const string t = row[i].type().sql_name(); 841 842 if (t.find("DATETIME")!=string::npos) 843 typ[i] = 'd'; 851 string t = row[i].type().sql_name(); 852 853 bool skip = false; 854 855 // Remove trailing " NULL" 856 if (t.find(" NOT NULL")==t.size()-9) 857 t = t.substr(0, t.size()-9); 858 if (t.find(" NULL")==t.size()-5) 859 t = t.substr(0, t.size()-5); 860 861 // Get FileEntry description corresponding to the sql type 862 const auto it = FileEntry::LUT.sql(t); 863 864 // Skip all columns that do not follow a convertible type 865 if (it==FileEntry::LUT.end()) 866 { 867 skip = true; 868 skipno++; 869 } 870 871 // For valid colums, check if they are of a type that can not be written to a root file 872 if (!skip && (it->type==FileEntry::kVarchar || it->type==FileEntry::kChar)) 873 { 874 skip = true; 875 skipch++; 876 } 877 878 // Check if there is any user request for skipping a column 879 if (!skip) 880 { 881 for (auto pattern=_ignore.cbegin(); pattern!=_ignore.cend(); pattern++) 882 { 883 if (boost::regex_match(l[i], boost::regex(*pattern))) 884 { 885 skip = true; 886 skipreg++; 887 break; 888 } 889 } 890 } 891 892 // Skip all columns that start with an @ (variable names) 893 if (!skip && l[i][0]=='@') 894 { 895 skip = true; 896 skipat++; 897 } 898 899 // Create the 'leaflist'. If no accurate conversion is requested, create doubles for all leaves 900 const string leaflist = l[i] + "/" + (accurate ? it->branch : 'D'); 901 902 if (verbose>1) 903 cout << (skip?" - ":" + ") << branch.c_str() << " [" << t << "] {" << (it==FileEntry::LUT.end()?'-':it->branch) << "}\n"; 904 905 // Create the container entry (must be emplace_back due to the std::string) 906 if (accurate) 907 container.emplace_back(leaflist, it->type); 844 908 else 845 if (t.find("DATE")!=string::npos) 846 typ[i] = 'D'; 847 else 848 if (t.find("TIME")!=string::npos) 849 typ[i] = 'T'; 850 else 851 if (t.find("VARCHAR")!=string::npos) 852 typ[i] = 'V'; 853 else 854 if (t.find("CHAR")!=string::npos) 855 typ[i] = 'C'; 856 857 bool found = false; 858 for (auto pattern=_ignore.cbegin(); pattern!=_ignore.cend(); pattern++) 859 { 860 if (boost::regex_match(l[i], boost::regex(*pattern))) 861 { 862 found = true; 863 typ[i] = '-'; 864 skipreg++; 865 break; 866 } 867 } 868 869 if (l[i][0]=='@') 870 { 871 typ[i] = '@'; 872 skipat++; 873 } 874 875 const bool use = l[i][0]!='@' && typ[i]!='V' && typ[i]!='C' && !found; 876 877 if (verbose>1) 878 cout << (use?" + ":" - ") << l[i].c_str() << " [" << t << "] {" << typ[i] << "}\n"; 879 880 if (use) 881 { 882 // string name = l[i]; 883 // for (const auto &m: mymap) 884 // name = boost::regex_replace(l[i], boost::regex(m.first), m.second); 885 886 for (auto it=ttree.begin(); it!=ttree.end(); it++) 887 it[0]->Branch(l[i].c_str(), buf.data()+i); 888 cols++; 889 } 909 container.emplace_back(leaflist, "", it->type); 910 911 if (skip) 912 continue; 913 914 // Create corresponding branches in all trees 915 for (auto itree=ttree.begin(); itree!=ttree.end(); itree++) 916 itree[0]->Branch(l[i].c_str(), container[i].ptr, branch.c_str()); 917 918 cols++; 890 919 } 891 920 // ------------------------------------------------------------------------- … … 895 924 if (verbose>0) 896 925 { 926 if (skipno) 927 cout << skipno << " branches skipped because no suitable type available." << endl; 928 if (skipch) 929 cout << skipch << " branches skipped because type is a character string." << endl; 897 930 if (skipreg) 898 931 cout << skipreg << " branches skipped due to ignore list." << endl; … … 994 1027 } 995 1028 996 switch (typ[idx])1029 if (accurate) 997 1030 { 998 case 'd': 999 buf[idx] = time_t((mysqlpp::DateTime)(*col)); 1000 break; 1001 1002 case 'D': 1003 buf[idx] = time_t((mysqlpp::Date)(*col)); 1004 break; 1005 1006 case 'T': 1007 buf[idx] = time_t((mysqlpp::Time)(*col)); 1008 break; 1009 1010 case 'V': 1011 case 'C': 1012 case '-': 1013 case '@': 1014 break; 1015 1016 default: 1017 buf[idx] = atof(col->c_str()); 1031 // Do an accurate type conversion and assign to the memory allocated as branch-address 1032 switch (container[idx].type) 1033 { 1034 case FileEntry::kBool: Convert<bool> (container[idx], *col); break; 1035 case FileEntry::kFloat: Convert<float> (container[idx], *col); break; 1036 case FileEntry::kDecimal: 1037 case FileEntry::kNumeric: 1038 case FileEntry::kDouble: Convert<double> (container[idx], *col); break; 1039 case FileEntry::kUInt64: Convert<uint64_t>(container[idx], *col); break; 1040 case FileEntry::kInt64: Convert<int64_t> (container[idx], *col); break; 1041 case FileEntry::kUInt32: Convert<uint32_t>(container[idx], *col); break; 1042 case FileEntry::kInt32: Convert<int32_t> (container[idx], *col); break; 1043 case FileEntry::kUInt16: Convert<uint16_t>(container[idx], *col); break; 1044 case FileEntry::kInt16: Convert<int16_t> (container[idx], *col); break; 1045 case FileEntry::kUInt8: Convert<uint8_t> (container[idx], *col); break; 1046 case FileEntry::kInt8: 1047 case FileEntry::kDate: 1048 *reinterpret_cast<uint64_t*>(container[idx].ptr) = static_cast<time_t>(mysqlpp::Date(*col)); 1049 break; 1050 case FileEntry::kDateTime: 1051 *reinterpret_cast<uint64_t*>(container[idx].ptr) = static_cast<time_t>(mysqlpp::DateTime(*col)); 1052 break; 1053 case FileEntry::kTime: 1054 *reinterpret_cast<uint32_t*>(container[idx].ptr) = static_cast<time_t>(mysqlpp::Time(*col)); 1055 break; 1056 default: 1057 break; 1058 } 1059 } 1060 else 1061 { 1062 // Convert everything to double, no matter what... and assign to the memory allocated as branch-address 1063 switch (container[idx].type) 1064 { 1065 case FileEntry::kBool: 1066 case FileEntry::kFloat: 1067 case FileEntry::kDecimal: 1068 case FileEntry::kNumeric: 1069 case FileEntry::kDouble: 1070 case FileEntry::kUInt64: 1071 case FileEntry::kInt64: 1072 case FileEntry::kUInt32: 1073 case FileEntry::kInt32: 1074 case FileEntry::kUInt16: 1075 case FileEntry::kInt16: 1076 case FileEntry::kUInt8: 1077 case FileEntry::kInt8: 1078 Convert<double>(container[idx], *col); 1079 break; 1080 case FileEntry::kDate: 1081 *reinterpret_cast<double*>(container[idx].ptr) = static_cast<time_t>(mysqlpp::Date(*col)); 1082 break; 1083 case FileEntry::kDateTime: 1084 *reinterpret_cast<double*>(container[idx].ptr) = static_cast<time_t>(mysqlpp::DateTime(*col)); 1085 break; 1086 case FileEntry::kTime: 1087 *reinterpret_cast<double*>(container[idx].ptr) = static_cast<time_t>(mysqlpp::Time(*col)); 1088 break; 1089 default: 1090 break; 1091 } 1018 1092 } 1019 1093 }
Note:
See TracChangeset
for help on using the changeset viewer.