From: Warren Young Date: December 11 2007 3:58am Subject: Re: Mismatch between query results and SSQLS column count List-Archive: http://lists.mysql.com/plusplus/7253 Message-Id: <475E0AEC.5000708@etr-usa.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Drew M. wrote: > > My original thinking was simply to replace an obscure exception with > one that was a little more informative. If your ssqls structure and > table (or query) didn't match, I think this would be hard to track > down unless the code threw an exception. This I did perceive, but I think making the library resilient in the face of DB schema changes makes more sense than making it complain. Neither crashes nor exceptions -- no matter how helpfully worded their error text -- are a good response to the database changing out from under the program. In my experience, the most common such "problem" is just a new column being added, so the app should just cruise right on, ignoring the new column, doing what it always did with the subset of columns it already knows about. I wish we could make it optional, so the B&D types can get "fail hard" behavior if they want it, but the only way I can think of to do that is through the OptionalExceptions mechanism, but I think you'd have to turn off the flag too early in a lot of cases to make it desirable. Consider Query::storein(): many things happen before it starts translating data from Row form to SSQLS, and you might want exceptions for failures here but not in the translation. We can solve this in SSQLS v2, where we can set a flag on the SSQLS itself to control such behavior. > - $popul .= " s->I$j = row.at(O$j).conv(T$j());"; > - $popul .= "\n" unless $j == $i; > + $popul .= " if( (*i) == s->names[O$j]) {\n"; > + $popul .= " s->I$j = row[(*i).c_str()].conv(T$j());\n"; > + $popul .= " continue;\n"; > + $popul .= " }\n"; I guess this patch is against 2.3.2? I didn't try it, but it seems reasonable if so. In fact, I think it's the only way it could work in 2.3.2 if you wish to keep the ABI intact. If anyone wants this behavior in 2.3.2, they should apply this. I had this feature in mind for v3.0, though, where the core of it can be done much more simply due to recent changes in Row: Index: lib/custom.pl =================================================================== --- lib/custom.pl (revision 1988) +++ lib/custom.pl (working copy) @@ -57,6 +57,7 @@ #ifndef MYSQLPP_CUSTOM_H #define MYSQLPP_CUSTOM_H +#include "noexceptions.h" #include "sql_types.h" #include @@ -295,7 +296,7 @@ $parm_simple2c_b .= ", " unless $j == $i; $defs .= " T$j I$j;"; $defs .= "\n" unless $j == $i; - $popul .= " s->I$j = row.at(O$j).conv(T$j());"; + $popul .= " s->I$j = row[N$j].conv(T$j());"; $popul .= "\n" unless $j == $i; $names .= " N$j "; $names .= ",\n" unless $j == $i; @@ -846,6 +847,7 @@ template void populate_##NAME (NAME *s, const mysqlpp::Row &row) { + mysqlpp::NoExceptions ignore_schema_mismatches(row); $popul } That last change is the key: Row::operator[](const char*) used to throw an exception unconditionally when you indexed it on a field that doesn't exist. Now it's optional, allowing the code to just go right on truckin' if there's a schema mismatch. There were a bunch of ancillary changes required due to heretofore unrecognized limitations in MySQL++, plus some side things I needed to tackle for completeness. Say 'svn diff -r1989:1991' if you want to see the whole story. Thanks anyway for your effort. The patch directed me to the right area of the code.