Index: /trunk/FACT++/src/root2sql.cc
===================================================================
--- /trunk/FACT++/src/root2sql.cc	(revision 19145)
+++ /trunk/FACT++/src/root2sql.cc	(revision 19146)
@@ -69,4 +69,5 @@
         ("duplicate",      vars<string>(),            "Specifies an assignment_list for an 'ON DUPLICATE KEY UPDATE' expression")
         ("ignore-errors",  po_switch(),               "Adds the IGNORE keyword to the INSERT query (turns errors into warnings, ignores rows with errors)")
+        ("const.*",        var<string>(),             "Insert a constant number into the given column (--const.mycolumn=5). A special case is `/..../N/`")
         ;
 
@@ -183,4 +184,11 @@
         "are marked as (-ignored-).\n"
         "\n"
+        "A constant value for the given file can be inserted by using the --const directive. "
+        "For example --const.mycolumn=42 would insert 42 into a column called mycolumn. "
+        "The column is created as INT UNSIGNED as default which can be altered by "
+        "--sql-type. A special case is a value of the form `/regex/N/`. Here, the given "
+        "regular expression is applied to the filename and N specifies the N-th "
+        "sub-sequence which matches. To debug what matches, verbosity can be set to 3.\n"
+        "\n"
         "If a query failed, the query is printed to stderr together with the error message. "
         "For the main INSERT query, this is only true if the verbosity level is at least 2 "
@@ -198,4 +206,5 @@
 {
     kNone = 0,
+    kConst,
     kFloat,
     kDouble,
@@ -222,31 +231,47 @@
 struct Container
 {
+    static map<void*, size_t> counter;
+
     string branch; // branch name
     string column; // column name
     BasicType_t type;
+    size_t num;
     void *ptr;
 
-    Container(const string &b, const string &c, const BasicType_t &t) : branch(b), column(c), type(t), ptr(0)
+    Container(const string &b, const string &c, const BasicType_t &t, const size_t &n) : branch(b), column(c), type(t), num(n), ptr(0)
     {
         switch (t)
         {
-        case kFloat:  ptr = new Float_t;   break;
-        case kDouble: ptr = new Double_t;  break;
-        case kInt16:  ptr = new Short_t;   break;
-        case kUInt16: ptr = new UShort_t;  break;
-        case kInt32:  ptr = new Int_t;     break;
-        case kUInt32: ptr = new UInt_t;    break;
-        case kInt64:  ptr = new Long64_t;  break;
-        case kUInt64: ptr = new ULong64_t; break;
+        case kFloat:  ptr = new Float_t[n];   break;
+        case kDouble: ptr = new Double_t[n];  break;
+        case kInt16:  ptr = new Short_t[n];   break;
+        case kUInt16: ptr = new UShort_t[n];  break;
+        case kInt32:  ptr = new Int_t[n];     break;
+        case kUInt32: ptr = new UInt_t[n];    break;
+        case kInt64:  ptr = new Long64_t[n];  break;
+        case kUInt64: ptr = new ULong64_t[n]; break;
+        case kConst:
         case kNone:
             break;
         }
-    }
+        counter[ptr]++;
+    }
+    Container(const string &c, const string &value) : branch(value), column(c), type(kConst), num(1), ptr(0)
+    {
+    }
+
+    Container(const Container &c) : branch(c.branch), column(c.column), type(c.type), num(c.num), ptr(c.ptr)
+    {
+        counter[ptr]++;
+    }
+
     ~Container()
     {
-        //::operator delete(ptr); // It seems root is deleting it already
-    }
-
-    string fmt() const
+        counter[ptr]--;
+        if (counter[ptr]==0)
+            ::operator delete[](ptr); // It seems root is deleting it already
+    }
+
+    string fmt(const size_t &index) const
     {
         ostringstream str;
@@ -254,12 +279,13 @@
         switch (type)
         {
-        case kFloat:   str << setprecision(8) << *reinterpret_cast<Float_t*>(ptr);  break;
-        case kDouble:  str << setprecision(16) << *reinterpret_cast<Double_t*>(ptr); break;
-        case kInt16:   str << *reinterpret_cast<Short_t*>(ptr); break;
-        case kUInt16:  str << *reinterpret_cast<UShort_t*>(ptr); break;
-        case kInt32:   str << *reinterpret_cast<Int_t*>(ptr); break;
-        case kUInt32:  str << *reinterpret_cast<UInt_t*>(ptr); break;
-        case kInt64:   str << *reinterpret_cast<Long64_t*>(ptr); break;
-        case kUInt64:  str << *reinterpret_cast<ULong64_t*>(ptr); break;
+        case kFloat:   str << setprecision(8) << reinterpret_cast<Float_t*>(ptr)[index];  break;
+        case kDouble:  str << setprecision(16) << reinterpret_cast<Double_t*>(ptr)[index]; break;
+        case kInt16:   str << reinterpret_cast<Short_t*>(ptr)[index]; break;
+        case kUInt16:  str << reinterpret_cast<UShort_t*>(ptr)[index]; break;
+        case kInt32:   str << reinterpret_cast<Int_t*>(ptr)[index]; break;
+        case kUInt32:  str << reinterpret_cast<UInt_t*>(ptr)[index]; break;
+        case kInt64:   str << reinterpret_cast<Long64_t*>(ptr)[index]; break;
+        case kUInt64:  str << reinterpret_cast<ULong64_t*>(ptr)[index]; break;
+        case kConst:   str << branch; break;
         case kNone:
             break;
@@ -272,4 +298,6 @@
     }
 };
+
+map<void*, size_t> Container::counter;
 
 void ErrorHandlerAll(Int_t level, Bool_t abort, const char *location, const char *msg)
@@ -387,4 +415,46 @@
     vector<Container> vec;
 
+    const auto fixed = conf.GetWildcardOptions("const.*");
+
+    for (auto it=fixed.cbegin(); it!=fixed.cend(); it++)
+    {
+        const string name = it->substr(6);
+        string val  = conf.Get<string>(*it);
+
+        boost::smatch match;
+        if (boost::regex_match(val, match, boost::regex("\\/(.+)\\/([0-9]*)\\/")))
+        {
+            string s = match[1];
+            size_t r = atoi(match[2].str().c_str());
+
+            if (boost::regex_search(file, match, boost::regex(s)))
+            {
+                if (verbose>2)
+                    for (size_t i=0; i<match.size(); i++)
+                        cout << "Regex match " << setw(2) << i << ": `" << match[i] << "`" << endl;
+
+                val = match[r];
+            }
+        }
+
+        if (verbose>2)
+            cout << "\n" << val << " [-const-]";
+        if (verbose>1)
+            cout << " (" << name << ")";
+
+        string sqltype = "INT UNSIGNED";
+
+        for (auto m=sqltypes.cbegin(); m!=sqltypes.cend(); m++)
+            if (m->first==name)
+                sqltype = m->second;
+
+        if (!vec.empty())
+            query += ",\n";
+        query += "   `"+name+"` "+sqltype+" NOT NULL COMMENT '--user--'";
+
+        vec.emplace_back(name, val);
+    }
+
+    const size_t nvec = vec.size();
 
     TIter Next(leaves);
@@ -395,8 +465,14 @@
 
         if (verbose>2)
-            cout << '\n' << o->GetName() << " [" << L->GetTypeName() << "]";
+            cout << '\n' << L->GetTitle() << " {" << L->GetTypeName() << "}";
+
+        if (L->GetLenStatic()=!L->GetLen())
+        {
+            if (verbose>2)
+                cout << " (-skipped-)";
+            continue;
+        }
 
         string name = o->GetName();
-
 
         bool found = false;
@@ -425,5 +501,5 @@
 
         if (verbose==2)
-            cout << '\n' << o->GetName() << " [" << L->GetTypeName() << "]";
+            cout << '\n' << L->GetTitle() << " {" << L->GetTypeName() << "}";
 
         for (auto m=mymap.cbegin(); m!=mymap.cend(); m++)
@@ -441,8 +517,18 @@
         if (!vec.empty())
             query += ",\n";
-        query += "   `"+name+"` "+sqltype+" NOT NULL COMMENT '"+o->GetName()+"'";
-
-        vec.emplace_back(o->GetName(), name, it->second.first);
-        T->SetBranchAddress(o->GetName(), vec.back().ptr);
+
+        const size_t N = L->GetLenStatic();
+        for (size_t i=0; i<N; i++)
+        {
+            query += "   `"+name;
+            if (N>1)
+                query += "["+to_string(i)+"]";
+            query += "` "+sqltype+" NOT NULL COMMENT '"+o->GetTitle()+"'";
+            if (N>1 && i!=N-1)
+                query += ",\n";
+        }
+
+        vec.emplace_back(o->GetTitle(), name, it->second.first, L->GetLenStatic());
+        T->SetBranchAddress(o->GetTitle(), vec.back().ptr);
     }
 
@@ -450,5 +536,9 @@
         cout << "\n\n";
     if (verbose>0)
-        cout << vec.size() << " leaves setup for reading." << endl;
+    {
+        if (nvec>0)
+            cout << nvec << " constant value column(s) configured." << endl;
+        cout << vec.size()-nvec << " leaf/leaves setup for reading." << endl;
+    }
 
     UInt_t datatype = 0;
@@ -458,5 +548,6 @@
     T->SetBranchStatus("*", 0);
     for (auto c=vec.cbegin(); c!=vec.cend(); c++)
-        T->SetBranchStatus(c->branch.c_str(), 1);
+        if (c->type!=kConst)
+            T->SetBranchStatus(c->branch.c_str(), 1);
 
     if (has_datatype)
@@ -467,4 +558,5 @@
     }
 
+
     // -------------------------------------------------------------------------
     // Checking for database connection
@@ -513,8 +605,8 @@
 
     if (!primary.empty())
-        query += ",\n   PRIMARY KEY USING BTREE (`"+boost::algorithm::join(primary, "`, `")+"`)\n";
+        query += ",\n   PRIMARY KEY USING BTREE (`"+boost::algorithm::join(primary, "`, `")+"`)";
 
     query +=
-        ")\n"
+        "\n)\n"
         "DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci\n";
     if (!engine.empty())
@@ -578,5 +670,16 @@
         if (c!=vec.cbegin())
             query += ",\n";
-        query += "   `"+c->column+"`";
+
+        const size_t N = c->num;
+        for (size_t i=0; i<N; i++)
+        {
+            if (N==1)
+                query += "   `"+c->column+"`";
+            else
+                query += "   `"+c->column+"["+to_string(i)+"]`";
+
+            if (N>1 && i!=N-1)
+                query += ",\n";
+        }
     }
 
@@ -604,8 +707,15 @@
                 query += ",\n";
 
-            query += "   "+c->fmt();
-
-            if (print_insert)
-                query += " /* "+c->column+" -> "+c->branch+" */";
+            const size_t N = c->num;
+            for (size_t i=0; i<N; i++)
+            {
+                query += "   "+c->fmt(i);
+
+                if (print_insert && i==0)
+                    query += " /* "+c->column+" -> "+c->branch+" */";
+
+                if (N>1 && i!=N-1)
+                    query += ",\n";
+            }
         }
         query += "\n)";
