CalcExtCastTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calctest/CalcExtCastTest.cpp#3 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "fennel/common/CommonPreamble.h"
00024 #include "fennel/test/TestBase.h"
00025 #include "fennel/common/TraceSource.h"
00026 
00027 #include "fennel/tuple/TupleDataWithBuffer.h"
00028 #include "fennel/tuple/TuplePrinter.h"
00029 #include "fennel/calculator/CalcCommon.h"
00030 #include "fennel/calculator/StringToHex.h"
00031 #include "fennel/common/FennelExcn.h"
00032 
00033 #include <boost/test/test_tools.hpp>
00034 #include <boost/scoped_array.hpp>
00035 #include <string>
00036 #include <limits>
00037 #include <math.h>
00038 
00039 
00040 using namespace fennel;
00041 using namespace std;
00042 
00043 class CalcExtCastTest : virtual public TestBase, public TraceSource
00044 {
00045     void testCalcExtCastStringToChar();
00046     void testCalcExtCastStringToVarChar();
00047     void testCalcExtCastBooleanToChar();
00048     void testCalcExtCastBooleanToVarChar();
00049     void testCalcExtCastExactToChar();
00050     void testCalcExtCastExactToVarChar();
00051     void testCalcExtCastDecimalToChar();
00052     void testCalcExtCastDecimalToVarChar();
00053     void testCalcExtCastBigExactToString();
00054     void testCalcExtCastExactToStringTruncates();
00055     void testCalcExtCastDecimalToStringTruncates();
00056     void testCalcExtCastCharToBoolean();
00057     void testCalcExtCastVarCharToBoolean();
00058     void testCalcExtCastCharToExact();
00059     void testCalcExtCastVarCharToExact();
00060     void testCalcExtCastCharToDecimal();
00061     void testCalcExtCastVarCharToDecimal();
00062     void testCalcExtCastStringToExactFails();
00063     void testCalcExtCastStringToDecimalFails();
00064     void testCalcExtCastStringToDecimalMinMax();
00065     void testCalcExtCastStringToDecimalRange();
00066     void testCalcExtCastStringToApprox();
00067     void testCalcExtCastApproxToString();
00068 
00069     // TODO: Move these calc-test utils up to a new base class.
00070     // TODO: Clearer boost error messages for wrong value in tuple.
00071     // REVIEW mb: Might be clearer if tests always printed calc outputs.
00072     int cmpTupStr(TupleDatum const & tup, char const * const str);
00073     int cmpTupStr(TupleDatum const & tup, const string& str);
00074     int cmpTupBool(TupleDatum const & tup, bool val);
00075     int cmpTupInt(TupleDatum const & tup, int val);
00076     int cmpTupInt64(TupleDatum const & tup, int64_t val);
00077     int cmpTupNull(TupleDatum const & tup);
00078     int cmpTupDouble(TupleDatum const & tup, double val);
00079     void printOutput(TupleData const & tup, Calculator const & calc);
00080     void refLocalOutput(ostringstream& pg, int count);
00081     string minInt64String();
00082     string maxInt64String();
00083     string rpad(string s, int size, char pad = ' ');
00084 
00085     static const bool verbose = true; // print more test output
00086 
00087     static const char* truncErr;
00088     static const char* invalidCharErr;
00089     static const char* outOfRangeErr;
00090 
00091 public:
00092     explicit CalcExtCastTest()
00093         : TraceSource(shared_from_this(),"CalcExtCastTest")
00094     {
00095         srand(time(NULL));
00096         CalcInit::instance();
00097         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastStringToChar);
00098         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastStringToVarChar);
00099         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastBooleanToVarChar);
00100         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastBooleanToChar);
00101         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastExactToVarChar);
00102         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastExactToChar);
00103         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastDecimalToChar);
00104         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastDecimalToVarChar);
00105         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastBigExactToString);
00106         FENNEL_UNIT_TEST_CASE(
00107             CalcExtCastTest, testCalcExtCastExactToStringTruncates); // errors
00108         FENNEL_UNIT_TEST_CASE(
00109             CalcExtCastTest, testCalcExtCastDecimalToStringTruncates); // errors
00110         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastCharToBoolean);
00111         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastVarCharToBoolean);
00112         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastCharToExact);
00113         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastVarCharToExact);
00114         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastCharToDecimal);
00115         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastVarCharToDecimal);
00116         FENNEL_UNIT_TEST_CASE(
00117             CalcExtCastTest, testCalcExtCastStringToExactFails);
00118         FENNEL_UNIT_TEST_CASE(
00119             CalcExtCastTest, testCalcExtCastStringToDecimalFails);
00120         FENNEL_UNIT_TEST_CASE(
00121             CalcExtCastTest, testCalcExtCastStringToDecimalMinMax);
00122         FENNEL_UNIT_TEST_CASE(
00123             CalcExtCastTest, testCalcExtCastStringToDecimalRange);
00124         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastStringToApprox);
00125         FENNEL_UNIT_TEST_CASE(CalcExtCastTest, testCalcExtCastApproxToString);
00126     }
00127 
00128     virtual ~CalcExtCastTest()
00129     {
00130     }
00131 };
00132 
00133 const char * CalcExtCastTest::truncErr = "22001";
00134 const char * CalcExtCastTest::invalidCharErr = "22018";
00135 const char * CalcExtCastTest::outOfRangeErr = "22003";
00136 
00137 // returns the minimum int64_t value, as a string.
00138 string CalcExtCastTest::minInt64String()
00139 {
00140     ostringstream os("");
00141     os << dec << numeric_limits<int64_t>::min();
00142     return os.str();
00143 }
00144 
00145 // returns the maximum int64_t value, as a string.
00146 string CalcExtCastTest::maxInt64String()
00147 {
00148     ostringstream os("");
00149     os << dec << numeric_limits<int64_t>::max();
00150     return os.str();
00151 }
00152 
00153 // right-pads a string to desired size
00154 string
00155 CalcExtCastTest::rpad(string s, int size, char pad)
00156 {
00157     int n = size - s.size();
00158     if (n > 0) {
00159         s.append(n, pad);
00160     }
00161     return s;
00162 }
00163 
00164 int
00165 CalcExtCastTest::cmpTupInt(TupleDatum const & tup, int val)
00166 {
00167     if (cmpTupNull(tup)) {
00168         return 1;
00169     }
00170     return *(reinterpret_cast<int*>
00171              (const_cast<PBuffer>(tup.pData))) - val;
00172 }
00173 
00174 int
00175 CalcExtCastTest::cmpTupDouble(TupleDatum const & tup, double val)
00176 {
00177     if (cmpTupNull(tup)) {
00178         return 1;
00179     }
00180     double tval = * reinterpret_cast<double*>
00181         (const_cast<PBuffer>(tup.pData));
00182     if (fabs(tval - val) < 0.00001) {
00183         return 0;
00184     }
00185     return (tval > val) ? 1 : -1;
00186 }
00187 
00188 int
00189 CalcExtCastTest::cmpTupInt64(
00190     TupleDatum const & tup,
00191     int64_t val)
00192 {
00193     if (cmpTupNull(tup)) {
00194         return 1;
00195     }
00196     return *(reinterpret_cast<int64_t*>
00197              (const_cast<PBuffer>(tup.pData))) - val;
00198 }
00199 
00200 int
00201 CalcExtCastTest::cmpTupStr(
00202     TupleDatum const & tup,
00203     const string& s)
00204 {
00205     return cmpTupStr(tup, s.c_str());
00206 }
00207 
00208 int
00209 CalcExtCastTest::cmpTupStr(
00210     TupleDatum const & tup,
00211     char const * const str)
00212 {
00213     if (cmpTupNull(tup)) {
00214         return 1;
00215     }
00216     int len = strlen(str);
00217     BOOST_CHECK_EQUAL(len, tup.cbData);
00218     return strncmp(
00219         reinterpret_cast<char *>(const_cast<PBuffer>(tup.pData)),
00220         str,
00221         len);
00222 }
00223 
00224 int
00225 CalcExtCastTest::cmpTupBool(TupleDatum const & tup, bool val)
00226 {
00227     if (cmpTupNull(tup)) {
00228         return 0;
00229     }
00230     return *(reinterpret_cast<bool*>
00231              (const_cast<PBuffer>(tup.pData))) == val;
00232 }
00233 
00234 int
00235 CalcExtCastTest::cmpTupNull(TupleDatum const & tup)
00236 {
00237     return ((const_cast<PBuffer>(tup.pData)) == NULL)? 1 : 0;
00238 }
00239 
00240 // for nitty-gritty debugging. sadly, doesn't use BOOST_MESSAGE.
00241 void
00242 CalcExtCastTest::printOutput(
00243     TupleData const & tup,
00244     Calculator const & calc)
00245 {
00246     if (verbose) {
00247         TuplePrinter tuplePrinter;
00248         tuplePrinter.print(cout, calc.getOutputRegisterDescriptor(), tup);
00249         cout << endl;
00250     }
00251 }
00252 
00253 
00254 // copy-by-reference locals into identical output register
00255 void
00256 CalcExtCastTest::refLocalOutput(
00257     ostringstream& pg,
00258     int count)
00259 {
00260     int i;
00261 
00262     for (i = 0; i < count; i++) {
00263         pg << "REF O" << i << ", L" << i << ";" << endl;
00264     }
00265 }
00266 
00267 
00268 void
00269 CalcExtCastTest::testCalcExtCastStringToChar()
00270 {
00271     ostringstream pg(""), outloc("");
00272 
00273     outloc << "c,5, c,5, c,5, c,5, c,5, c,5, c,5, c,5;" << endl;
00274 
00275     pg << "O " << outloc.str();
00276     pg << "L " << outloc.str();
00277     pg << "C vc,3, vc,8, c,3, c,8, vc,8, c,8, vc,8, c,8;" << endl;
00278     pg << "V 0x" << stringToHex("ABC");
00279     pg << ", 0x" << stringToHex("DEFGH");
00280     pg << ", 0x" << stringToHex("ZYX");
00281     pg << ", 0x" << stringToHex("WVUTS   ");
00282     pg << ", 0x" << stringToHex("IJKLMNOP");
00283     pg << ", 0x" << stringToHex("RQPONMLK");
00284     pg << ",,;" << endl;
00285     pg << "T;" << endl;
00286 
00287     // vc(3) -> c(5)
00288     pg << "CALL 'castA(L0, C0);" << endl;
00289 
00290     // vc(8), length5 -> c(5)
00291     pg << "CALL 'castA(L1, C1);" << endl;
00292 
00293     // c(3) -> c(5)
00294     pg << "CALL 'castA(L2, C2);" << endl;
00295 
00296     // c(8) -> c(5)
00297     pg << "CALL 'castA(L3, C3);" << endl;
00298 
00299     // vc(8), length 8 -> c(5) = 22001
00300     pg << "CALL 'castA(L4, C4);" << endl;
00301 
00302     // c(8) -> c(5) = 22001
00303     pg << "CALL 'castA(L5, C5);" << endl;
00304 
00305     // null vc(8) -> c(5)
00306     pg << "CALL 'castA(L6, C6);" << endl;
00307 
00308     // null c(8) -> c(5)
00309     pg << "CALL 'castA(L7, C7);" << endl;
00310 
00311     // make output available
00312     refLocalOutput(pg, 8);
00313 
00314     Calculator calc(0);
00315 
00316     try {
00317         calc.assemble(pg.str().c_str());
00318     } catch (FennelExcn& ex) {
00319         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00320         BOOST_MESSAGE(pg.str());
00321         BOOST_REQUIRE(0);
00322     }
00323 
00324     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00325     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00326 
00327     calc.bind(&inTuple, &outTuple);
00328     calc.exec();
00329     printOutput(outTuple, calc);
00330     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00331 
00332     // vc(3) -> c(5)
00333     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[0], "ABC  "));
00334 
00335     // vc(8), length 5 -> c(5)
00336     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], "DEFGH"));
00337 
00338     // c(3) - > c(5)
00339     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "ZYX  "));
00340 
00341     // c(8) -> c(5)
00342     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "WVUTS"));
00343 
00344     // vc(8), length 8 -> c(5) = 22001
00345     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[4], "IJKLM"));
00346     // TODO: when 22001 is thrown as a warning, re-enable this
00347     // BOOST_CHECK_EQUAL(iter->pc, 4);
00348     // BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
00349     // iter++;
00350 
00351     // c(8) -> c(5) = 22001
00352     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], "RQPON"));
00353     // TODO: when 22001 is thrown as a warning, re-enable this
00354     // BOOST_CHECK_EQUAL(iter->pc, 5);
00355     // BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
00356     // iter++;
00357 
00358     // null vc(8) -> c(5)
00359     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[6]));
00360 
00361     // null c(8) -> c(5)
00362     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[7]));
00363 
00364     BOOST_CHECK(iter == calc.mWarnings.end());
00365 }
00366 
00367 
00368 void
00369 CalcExtCastTest::testCalcExtCastStringToVarChar()
00370 {
00371     ostringstream pg(""), outloc("");
00372 
00373     outloc << "vc,5, vc,5, vc,5, vc,5, vc,5, vc,5, vc,5, vc,5;" << endl;
00374 
00375     pg << "O " << outloc.str();
00376     pg << "L " << outloc.str();
00377     pg << "C vc,3, vc,8, c,3, c,8, vc,8, c,8, vc,8, c,8;" << endl;
00378     pg << "V 0x" << stringToHex("ABC");
00379     pg << ", 0x" << stringToHex("DEFGH");
00380     pg << ", 0x" << stringToHex("ZYX");
00381     pg << ", 0x" << stringToHex("WVUTS   ");
00382     pg << ", 0x" << stringToHex("IJKLMNOP");
00383     pg << ", 0x" << stringToHex("RQPONMLK");
00384     pg << ",,;" << endl;
00385     pg << "T;" << endl;
00386 
00387     // vc(3) -> vc(5)
00388     pg << "CALL 'castA(L0, C0);" << endl;
00389 
00390     // vc(8), length5 -> vc(5)
00391     pg << "CALL 'castA(L1, C1);" << endl;
00392 
00393     // c(3) -> vc(5)
00394     pg << "CALL 'castA(L2, C2);" << endl;
00395 
00396     // c(8) -> vc(5)
00397     pg << "CALL 'castA(L3, C3);" << endl;
00398 
00399     // vc(8), length 8 -> vc(5) = 22001
00400     pg << "CALL 'castA(L4, C4);" << endl;
00401 
00402     // c(8) -> vc(5) = 22001
00403     pg << "CALL 'castA(L5, C5);" << endl;
00404 
00405     // null vc(8) -> vc(5)
00406     pg << "CALL 'castA(L6, C6);" << endl;
00407 
00408     // null c(8) -> vc(5)
00409     pg << "CALL 'castA(L7, C7);" << endl;
00410 
00411     // make output available
00412     refLocalOutput(pg, 8);
00413 
00414     Calculator calc(0);
00415 
00416     try {
00417         calc.assemble(pg.str().c_str());
00418     } catch (FennelExcn& ex) {
00419         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00420         BOOST_MESSAGE(pg.str());
00421         BOOST_REQUIRE(0);
00422     }
00423 
00424     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00425     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00426 
00427     calc.bind(&inTuple, &outTuple);
00428     calc.exec();
00429     printOutput(outTuple, calc);
00430     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00431 
00432     // vc(3) -> vc(5)
00433     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[0], "ABC"));
00434 
00435     // vc(8), length 5 -> vc(5)
00436     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], "DEFGH"));
00437 
00438     // c(3) - > vc(5)
00439     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "ZYX"));
00440 
00441     // c(8) -> vc(5)
00442     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "WVUTS"));
00443 
00444     // vc(8), length 8 -> vc(5) = 22001
00445     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[4], "IJKLM"));
00446     // TODO: when 22001 is thrown as a warning, re-enable this
00447     // BOOST_CHECK_EQUAL(iter->pc, 4);
00448     // BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
00449     // iter++;
00450 
00451     // c(8) -> vc(5) = 22001
00452     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], "RQPON"));
00453     // TODO: when 22001 is thrown as a warning, re-enable this
00454     // BOOST_CHECK_EQUAL(iter->pc, 5);
00455     // BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
00456     // iter++;
00457 
00458     // null vc(8) -> vc(5)
00459     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[6]));
00460 
00461     // null c(8) -> vc(5)
00462     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[7]));
00463 
00464     BOOST_CHECK(iter == calc.mWarnings.end());
00465 }
00466 
00467 // cast booleans to char strings
00468 void
00469 CalcExtCastTest::testCalcExtCastBooleanToChar()
00470 {
00471     // int8 test values: (null, true, false),
00472     // cast to CHAR(3) and CHAR(4) and CHAR(5)
00473     ostringstream pg(""), outloc("");
00474     outloc <<  "c,3, c,3, c,3, c,4, c,4, c,4, c,5, c,5, c,5;" << endl;
00475     pg << "O " << outloc.str();
00476     pg << "L " << outloc.str();
00477     pg << "C bo, bo, bo;" << endl;
00478     pg << "V , 1, 0;" << endl;
00479     pg << "T;" << endl;
00480     // cast all to CHAR(3)
00481     for (int i = 0; i < 3; i++) {
00482         pg << "CALL 'castA(L" << i << ", C" << i << ");" << endl;
00483     }
00484     // cast all to CHAR(4)
00485     for (int i = 0; i < 3; i++) {
00486         pg << "CALL 'castA(L" << (i + 3) << ", C" << i << ");" << endl;
00487     }
00488     // cast all to CHAR(5)
00489     for (int i = 0; i < 3; i++) {
00490         pg << "CALL 'castA(L" << (i + 6) << ", C" << i << ");" << endl;
00491     }
00492     refLocalOutput(pg, 9);      // make output available
00493 
00494     Calculator calc(0);
00495     try {
00496         calc.assemble(pg.str().c_str());
00497     } catch (FennelExcn& ex) {
00498         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00499         BOOST_MESSAGE(pg.str());
00500         BOOST_REQUIRE(0);
00501     }
00502 
00503     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00504     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00505     calc.bind(&inTuple, &outTuple);
00506     calc.exec();
00507     printOutput(outTuple, calc);
00508     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00509 
00510     // check results:
00511     BOOST_CHECK(cmpTupNull(outTuple[0]));
00512 
00513     // true -> c(3) = invalid char
00514     BOOST_CHECK_EQUAL(iter->pc, 1);
00515     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
00516     iter++;
00517 
00518     // false -> c(3) = invalid char
00519     BOOST_CHECK_EQUAL(iter->pc, 2);
00520     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
00521     iter++;
00522 
00523     BOOST_CHECK(cmpTupNull(outTuple[3]));
00524     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[4], "TRUE"));
00525 
00526     // false -> c(4) = invalid char
00527     BOOST_CHECK_EQUAL(iter->pc, 5);
00528     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
00529     iter++;
00530 
00531     BOOST_CHECK(cmpTupNull(outTuple[6]));
00532     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[7], "TRUE "));
00533     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[8], "FALSE"));
00534     BOOST_CHECK(iter == calc.mWarnings.end());
00535 }
00536 
00537 // cast booleans to varchar strings
00538 void
00539 CalcExtCastTest::testCalcExtCastBooleanToVarChar()
00540 {
00541     // int8 test values: (null, true, false),
00542     // cast to VARCHAR(3) and VARCHAR(4) and VARCHAR(5)
00543     ostringstream pg(""), outloc("");
00544     outloc <<  "vc,3, vc,3, vc,3, vc,4, vc,4, vc,4, vc,5, vc,5, vc,5;" << endl;
00545     pg << "O " << outloc.str();
00546     pg << "L " << outloc.str();
00547     pg << "C bo, bo, bo;" << endl;
00548     pg << "V , 1, 0;" << endl;
00549     pg << "T;" << endl;
00550     // cast all to VARCHAR(3)
00551     for (int i = 0; i < 3; i++) {
00552         pg << "CALL 'castA(L" << i << ", C" << i << ");" << endl;
00553     }
00554     // cast all to VARCHAR(4)
00555     for (int i = 0; i < 3; i++) {
00556         pg << "CALL 'castA(L" << (i + 3) << ", C" << i << ");" << endl;
00557     }
00558     // cast all to VARCHAR(5)
00559     for (int i = 0; i < 3; i++) {
00560         pg << "CALL 'castA(L" << (i + 6) << ", C" << i << ");" << endl;
00561     }
00562     refLocalOutput(pg, 9);      // make output available
00563 
00564     Calculator calc(0);
00565     try {
00566         calc.assemble(pg.str().c_str());
00567     } catch (FennelExcn& ex) {
00568         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00569         BOOST_MESSAGE(pg.str());
00570         BOOST_REQUIRE(0);
00571     }
00572 
00573     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00574     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00575     calc.bind(&inTuple, &outTuple);
00576     calc.exec();
00577     printOutput(outTuple, calc);
00578     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00579 
00580     // check results:
00581     BOOST_CHECK(cmpTupNull(outTuple[0]));
00582 
00583     // true -> vc(3) = invalid char
00584     BOOST_CHECK_EQUAL(iter->pc, 1);
00585     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
00586     iter++;
00587 
00588     // false -> vc(3) = invalid char
00589     BOOST_CHECK_EQUAL(iter->pc, 2);
00590     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
00591     iter++;
00592 
00593     BOOST_CHECK(cmpTupNull(outTuple[3]));
00594     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[4], "TRUE"));
00595 
00596     // false -> vc(4) = invalid char
00597     BOOST_CHECK_EQUAL(iter->pc, 5);
00598     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
00599     iter++;
00600 
00601     BOOST_CHECK(cmpTupNull(outTuple[6]));
00602     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[7], "TRUE"));
00603     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[8], "FALSE"));
00604     BOOST_CHECK(iter == calc.mWarnings.end());
00605 }
00606 
00607 // cast exact numbers to char strings
00608 void
00609 CalcExtCastTest::testCalcExtCastExactToChar()
00610 {
00611     // int8 test values: (null, 0, 10, -10),  cast to CHAR(3) and CHAR(16)
00612     ostringstream pg(""), outloc("");
00613     outloc <<  "c,3, c,3, c,3, c,3, c,16, c,16, c,16, c,16;" << endl;
00614     pg << "O " << outloc.str();
00615     pg << "L " << outloc.str();
00616     pg << "C s8, s8, s8, s8;" << endl;
00617     pg << "V , 0, 10, -10;" << endl;
00618     pg << "T;" << endl;
00619     // cast all to CHAR(3)
00620     for (int i = 0; i < 4; i++) {
00621         pg << "CALL 'castA(L" << i << ", C" << i << ");" << endl;
00622     }
00623     // cast all to CHAR(16)
00624     for (int i = 0; i < 4; i++) {
00625         pg << "CALL 'castA(L" << (i + 4) << ", C" << i << ");" << endl;
00626     }
00627     refLocalOutput(pg, 8);      // make output available
00628 
00629     Calculator calc(0);
00630     try {
00631         calc.assemble(pg.str().c_str());
00632     } catch (FennelExcn& ex) {
00633         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00634         BOOST_MESSAGE(pg.str());
00635         BOOST_REQUIRE(0);
00636     }
00637 
00638     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00639     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00640     calc.bind(&inTuple, &outTuple);
00641     calc.exec();
00642     printOutput(outTuple, calc);
00643     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00644 
00645     // check results:
00646     BOOST_CHECK(cmpTupNull(outTuple[0]));
00647     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], "0  "));
00648     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "10 "));
00649     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "-10"));
00650     BOOST_CHECK(cmpTupNull(outTuple[4]));
00651     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], "0               "));
00652     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[6], "10              "));
00653     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[7], "-10             "));
00654     BOOST_CHECK(iter == calc.mWarnings.end());
00655 }
00656 
00657 // cast exact numbers to varchar strings
00658 void
00659 CalcExtCastTest::testCalcExtCastExactToVarChar()
00660 {
00661     // int8 test values: (null, 0, 10, -10), cast to VARCHAR(3) and VARCHAR(16).
00662     ostringstream pg(""), outloc("");
00663     outloc <<  "vc,3, vc,3, vc,3, vc,3, vc,16, vc,16, vc,16, vc,16;" << endl;
00664     pg << "O " << outloc.str();
00665     pg << "L " << outloc.str();
00666     pg << "C s8, s8, s8, s8;" << endl;
00667     pg << "V , 0, 10, -10;" << endl;
00668     pg << "T;" << endl;
00669     // cast all to VARCHAR(3)
00670     for (int i = 0; i < 4; i++) {
00671         pg << "CALL 'castA(L" << i << ", C" << i << ");" << endl;
00672     }
00673     // cast all to VARCHAR(16)
00674     for (int i = 0; i < 4; i++) {
00675         pg << "CALL 'castA(L" << (i + 4) << ", C" << i << ");" << endl;
00676     }
00677     refLocalOutput(pg, 8);      // make output available
00678 
00679     Calculator calc(0);
00680     try {
00681         calc.assemble(pg.str().c_str());
00682     } catch (FennelExcn& ex) {
00683         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00684         BOOST_MESSAGE(pg.str());
00685         BOOST_REQUIRE(0);
00686     }
00687 
00688     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00689     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00690     calc.bind(&inTuple, &outTuple);
00691     calc.exec();
00692     printOutput(outTuple, calc);
00693     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00694 
00695     // check results:
00696     BOOST_CHECK(cmpTupNull(outTuple[0]));
00697     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], "0"));
00698     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "10"));
00699     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "-10"));
00700     BOOST_CHECK(cmpTupNull(outTuple[4]));
00701     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], "0"));
00702     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[6], "10"));
00703     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[7], "-10"));
00704     BOOST_CHECK(iter == calc.mWarnings.end());
00705 }
00706 
00707 // cast decimal numbers (with precision/scale) to char strings
00708 void
00709 CalcExtCastTest::testCalcExtCastDecimalToChar()
00710 {
00711     // decimal(5,2) test values: (null, 0, 10, -10.90, 4.30, -.09, .30),
00712     // cast to CHAR(6) and CHAR(16)
00713 
00714     // decimal(5,0) test values: (null, 0, 1000, -1090, 430, -9, 30),
00715     // cast to CHAR(5) and CHAR(16)
00716 
00717     // decimal(5,-2) test values: (null, 0, 100000, -109000, 43000, -900, 3000),
00718     // cast to CHAR(7) and CHAR(16)
00719 
00720     ostringstream pg(""), outloc("");
00721     outloc <<  "c,6, c,6, c,6, c,6, c,6, c,6, c,6, "
00722            <<  "c,16, c,16, c,16, c,16, c,16, c,16, c,16, "
00723            <<  "c,5, c,5, c,5, c,5, c,5, c,5, c,5, "
00724            <<  "c,16, c,16, c,16, c,16, c,16, c,16, c,16, "
00725            <<  "c,7, c,7, c,7, c,7, c,7, c,7, c,7, "
00726            <<  "c,16, c,16, c,16, c,16, c,16, c,16, c,16;" << endl;
00727     pg << "O " << outloc.str();
00728     pg << "L " << outloc.str();
00729     pg << "C s8, s8, s8, s8, s8, s8, s8, s4, s4, s4, s4;" << endl;
00730     pg << "V , 0, 1000, -1090, 430, -9, 30, 5, 2, 0, -2;" << endl;
00731     pg << "T;" << endl;
00732     // cast decimal(5,2) to CHAR(6)
00733     for (int i = 0; i < 7; i++) {
00734         pg << "CALL 'castA(L" << i << ", C" << i << ", C7, C8 );" << endl;
00735     }
00736     // cast decimal(5,2) to CHAR(16)
00737     for (int i = 0; i < 7; i++) {
00738         pg << "CALL 'castA(L" << (i + 7) << ", C" << i << ", C7, C8 );" << endl;
00739     }
00740 
00741     // cast decimal(5,0) to CHAR(5)
00742     for (int i = 0; i < 7; i++) {
00743         pg << "CALL 'castA(L" << (i + 14) << ", C" << i << ", C7, C9 );"
00744            << endl;
00745     }
00746     // cast decimal(5,0) to CHAR(16)
00747     for (int i = 0; i < 7; i++) {
00748         pg << "CALL 'castA(L" << (i + 21) << ", C" << i << ", C7, C9 );"
00749            << endl;
00750     }
00751 
00752     // cast decimal(5,-2) to CHAR(7)
00753     for (int i = 0; i < 7; i++) {
00754         pg << "CALL 'castA(L" << (i + 28) << ", C" << i << ", C7, C10 );"
00755            << endl;
00756     }
00757     // cast decimal(5,-2) to CHAR(16)
00758     for (int i = 0; i < 7; i++) {
00759         pg << "CALL 'castA(L" << (i + 35) << ", C" << i << ", C7, C10 );"
00760            << endl;
00761     }
00762 
00763     refLocalOutput(pg, 7*6);      // make output available
00764 
00765     Calculator calc(0);
00766     try {
00767         calc.assemble(pg.str().c_str());
00768     } catch (FennelExcn& ex) {
00769         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00770         BOOST_MESSAGE(pg.str());
00771         BOOST_REQUIRE(0);
00772     }
00773 
00774     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00775     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00776     calc.bind(&inTuple, &outTuple);
00777     calc.exec();
00778     printOutput(outTuple, calc);
00779     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00780 
00781     // check results:
00782     // decimal(5,2)
00783     BOOST_CHECK(cmpTupNull(outTuple[0]));
00784     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], ".00   "));
00785     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "10.00 "));
00786     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "-10.90"));
00787     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[4], "4.30  "));
00788     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], "-.09  "));
00789     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[6], ".30   "));
00790     BOOST_CHECK(cmpTupNull(outTuple[7]));
00791     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[8],  ".00             "));
00792     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[9],  "10.00           "));
00793     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[10], "-10.90          "));
00794     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[11], "4.30            "));
00795     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[12], "-.09            "));
00796     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[13], ".30             "));
00797 
00798     // decimal(5,0)
00799     BOOST_CHECK(cmpTupNull(outTuple[14]));
00800     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[15], "0    "));
00801     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[16], "1000 "));
00802     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[17], "-1090"));
00803     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[18], "430  "));
00804     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[19], "-9   "));
00805     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[20], "30   "));
00806     BOOST_CHECK(cmpTupNull(outTuple[21]));
00807     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[22], "0               "));
00808     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[23], "1000            "));
00809     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[24], "-1090           "));
00810     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[25], "430             "));
00811     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[26], "-9              "));
00812     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[27], "30              "));
00813 
00814     // decimal(5,-2)
00815     BOOST_CHECK(cmpTupNull(outTuple[28]));
00816     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[29], "0      "));
00817     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[30], "100000 "));
00818     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[31], "-109000"));
00819     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[32], "43000  "));
00820     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[33], "-900   "));
00821     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[34], "3000   "));
00822     BOOST_CHECK(cmpTupNull(outTuple[35]));
00823     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[36], "0               "));
00824     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[37], "100000          "));
00825     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[38], "-109000         "));
00826     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[39], "43000           "));
00827     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[40], "-900            "));
00828     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[41], "3000            "));
00829 }
00830 
00831 // cast decimal numbers (with precision/scale) to varchar strings
00832 void
00833 CalcExtCastTest::testCalcExtCastDecimalToVarChar()
00834 {
00835     // decimal(5,2) test values: (null, 0, 10, -10.90, 4.30, -.09, .30),
00836     // cast to VARCHAR(6) and VARCHAR(16)
00837 
00838     // decimal(5,0) test values: (null, 0, 1000, -1090, 430, -9, 30),
00839     // cast to VARCHAR(5) and VARCHAR(16)
00840 
00841     // decimal(5,-2) test values: (null, 0, 100000, -109000, 43000, -900, 3000),
00842     // cast to VARCHAR(7) and VARCHAR(16)
00843 
00844     ostringstream pg(""), outloc("");
00845     outloc <<  "vc,6, vc,6, vc,6, vc,6, vc,6, vc,6, vc,6, "
00846            <<  "vc,16, vc,16, vc,16, vc,16, vc,16, vc,16, vc,16, "
00847            <<  "vc,5, vc,5, vc,5, vc,5, vc,5, vc,5, vc,5, "
00848            <<  "vc,16, vc,16, vc,16, vc,16, vc,16, vc,16, vc,16, "
00849            <<  "vc,7, vc,7, vc,7, vc,7, vc,7, vc,7, vc,7, "
00850            <<  "vc,16, vc,16, vc,16, vc,16, vc,16, vc,16, vc,16;" << endl;
00851     pg << "O " << outloc.str();
00852     pg << "L " << outloc.str();
00853     pg << "C s8, s8, s8, s8, s8, s8, s8, s4, s4, s4, s4;" << endl;
00854     pg << "V , 0, 1000, -1090, 430, -9, 30, 5, 2, 0, -2;" << endl;
00855     pg << "T;" << endl;
00856     // cast decimal(5,2) to VARCHAR(6)
00857     for (int i = 0; i < 7; i++) {
00858         pg << "CALL 'castA(L" << i << ", C" << i << ", C7, C8 );" << endl;
00859     }
00860     // cast decimal(5,2) to VARCHAR(16)
00861     for (int i = 0; i < 7; i++) {
00862         pg << "CALL 'castA(L" << (i + 7) << ", C" << i << ", C7, C8 );" << endl;
00863     }
00864     // cast decimal(5,0) to VARCHAR(5)
00865     for (int i = 0; i < 7; i++) {
00866         pg << "CALL 'castA(L" << (i + 14) << ", C" << i << ", C7, C9 );"
00867            << endl;
00868     }
00869     // cast decimal(5,0) to VARCHAR(16)
00870     for (int i = 0; i < 7; i++) {
00871         pg << "CALL 'castA(L" << (i + 21) << ", C" << i << ", C7, C9 );"
00872            << endl;
00873     }
00874     // cast decimal(5,-2) to VARCHAR(7)
00875     for (int i = 0; i < 7; i++) {
00876         pg << "CALL 'castA(L" << (i + 28) << ", C" << i << ", C7, C10 );"
00877            << endl;
00878     }
00879     // cast decimal(5,-2) to VARCHAR(16)
00880     for (int i = 0; i < 7; i++) {
00881         pg << "CALL 'castA(L" << (i + 35) << ", C" << i << ", C7, C10 );"
00882            << endl;
00883     }
00884     refLocalOutput(pg, 7 * 6);      // make output available
00885 
00886     Calculator calc(0);
00887     try {
00888         calc.assemble(pg.str().c_str());
00889     } catch (FennelExcn& ex) {
00890         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00891         BOOST_MESSAGE(pg.str());
00892         BOOST_REQUIRE(0);
00893     }
00894 
00895     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00896     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00897     calc.bind(&inTuple, &outTuple);
00898     calc.exec();
00899     printOutput(outTuple, calc);
00900     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00901 
00902     // check results:
00903     // decimal(5,2)
00904     BOOST_CHECK(cmpTupNull(outTuple[0]));
00905     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], ".00"));
00906     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "10.00"));
00907     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "-10.90"));
00908     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[4], "4.30"));
00909     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], "-.09"));
00910     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[6], ".30"));
00911     BOOST_CHECK(cmpTupNull(outTuple[7]));
00912     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[8],  ".00"));
00913     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[9],  "10.00"));
00914     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[10], "-10.90"));
00915     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[11], "4.30"));
00916     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[12], "-.09"));
00917     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[13], ".30"));
00918 
00919     // decimal(5,0)
00920     BOOST_CHECK(cmpTupNull(outTuple[14]));
00921     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[15], "0"));
00922     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[16], "1000"));
00923     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[17], "-1090"));
00924     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[18], "430"));
00925     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[19], "-9"));
00926     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[20], "30"));
00927     BOOST_CHECK(cmpTupNull(outTuple[21]));
00928     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[22], "0"));
00929     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[23], "1000"));
00930     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[24], "-1090"));
00931     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[25], "430"));
00932     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[26], "-9"));
00933     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[27], "30"));
00934 
00935     // decimal(5,-2)
00936     BOOST_CHECK(cmpTupNull(outTuple[28]));
00937     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[29], "0"));
00938     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[30], "100000"));
00939     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[31], "-109000"));
00940     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[32], "43000"));
00941     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[33], "-900"));
00942     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[34], "3000"));
00943     BOOST_CHECK(cmpTupNull(outTuple[35]));
00944     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[36], "0"));
00945     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[37], "100000"));
00946     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[38], "-109000"));
00947     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[39], "43000"));
00948     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[40], "-900"));
00949     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[41], "3000"));
00950 }
00951 
00952 // cast large exact numbers to strings
00953 void
00954 CalcExtCastTest::testCalcExtCastBigExactToString()
00955 {
00956     // int8 test values: (MAX, MIN) cast to CHAR(32) and VARCHAR(32);
00957     ostringstream pg(""), outloc("");
00958     outloc <<  "vc,32, vc,32, c,32, c,32;" << endl;
00959     pg << "O " << outloc.str();
00960     pg << "L " << outloc.str();
00961     pg << "C s8, s8;" << endl;
00962     pg << "V " << maxInt64String() << ", " << minInt64String() << ";" << endl;
00963     pg << "T;" << endl;
00964     pg << "CALL 'castA(L0, C0);" << endl;
00965     pg << "CALL 'castA(L1, C1);" << endl;
00966     pg << "CALL 'castA(L2, C0);" << endl;
00967     pg << "CALL 'castA(L3, C1);" << endl;
00968     refLocalOutput(pg, 4);      // make output available
00969 
00970     Calculator calc(0);
00971     try {
00972         calc.assemble(pg.str().c_str());
00973     } catch (FennelExcn& ex) {
00974         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
00975         BOOST_MESSAGE(pg.str());
00976         BOOST_REQUIRE(0);
00977     }
00978 
00979     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
00980     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
00981     calc.bind(&inTuple, &outTuple);
00982     calc.exec();
00983     printOutput(outTuple, calc);
00984     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
00985 
00986     // check results:
00987     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[0], maxInt64String()));
00988     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], minInt64String()));
00989     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], rpad(maxInt64String(), 32)));
00990     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], rpad(minInt64String(), 32)));
00991     BOOST_CHECK(iter == calc.mWarnings.end());
00992 }
00993 
00994 // cast exact numbers to strings; truncates
00995 void
00996 CalcExtCastTest::testCalcExtCastExactToStringTruncates()
00997 {
00998     // int8 test values (1666, -1666) cast to VARCHAR(3) and CHAR(3)
00999     ostringstream pg(""), outloc("");
01000     outloc <<  "vc,3, vc,3, c,3, c,3;" << endl;
01001     pg << "O " << outloc.str();
01002     pg << "L " << outloc.str();
01003     pg << "C s8, s8;" << endl;
01004     pg << "V 1666, -1666;" << endl;
01005     pg << "T;" << endl;
01006     pg << "CALL 'castA(L0, C0);" << endl;
01007     pg << "CALL 'castA(L1, C1);" << endl;
01008     pg << "CALL 'castA(L2, C0);" << endl;
01009     pg << "CALL 'castA(L3, C1);" << endl;
01010     refLocalOutput(pg, 4);      // make output available
01011 
01012     Calculator calc(0);
01013     try {
01014         calc.assemble(pg.str().c_str());
01015     } catch (FennelExcn& ex) {
01016         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01017         BOOST_MESSAGE(pg.str());
01018         BOOST_REQUIRE(0);
01019     }
01020 
01021     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01022     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01023     calc.bind(&inTuple, &outTuple);
01024     calc.exec();
01025     printOutput(outTuple, calc);
01026     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01027 
01028     // check results:
01029     // 1666 -> vc(3) = truncates
01030     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[0], "166"));
01031     BOOST_CHECK_EQUAL(iter->pc, 0);
01032     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01033     iter++;
01034 
01035     // -1666 -> vc(3) = truncates
01036     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[1], "-16"));
01037     BOOST_CHECK_EQUAL(iter->pc, 1);
01038     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01039     iter++;
01040 
01041     // 1666 -> c(3) = truncates
01042     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], "166"));
01043     BOOST_CHECK_EQUAL(iter->pc, 2);
01044     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01045     iter++;
01046 
01047     // -1666 -> c(3) = truncates
01048     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[3], "-16"));
01049     BOOST_CHECK_EQUAL(iter->pc, 3);
01050     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01051     iter++;
01052     BOOST_CHECK(iter == calc.mWarnings.end());
01053 }
01054 
01055 
01056 // cast decimal numbers to strings; truncates
01057 void
01058 CalcExtCastTest::testCalcExtCastDecimalToStringTruncates()
01059 {
01060     // decimal(5,2) test values: (-10.9, -.09, .30),
01061     // decimal(5,0) test values: (-1090, -9, 30),
01062     // decimal(5,-2) test values: (-109000, -900, 3000),
01063 
01064     // cast to VARCHAR(3) and CHAR(3)
01065     ostringstream pg(""), outloc("");
01066     outloc <<  "vc,3, vc,3, vc,3, c,3, c,3, c,3, "
01067            <<  "vc,3, vc,3, vc,3, c,3, c,3, c,3, "
01068            <<  "vc,3, vc,3, vc,3, c,3, c,3, c,3;" << endl;
01069     pg << "O " << outloc.str();
01070     pg << "L " << outloc.str();
01071     pg << "C s8, s8, s8, s4, s4, s4, s4;" << endl;
01072     pg << "V -1090, -9, 30, 5, 2, 0, -2;" << endl;
01073     pg << "T;" << endl;
01074 
01075     pg << "CALL 'castA(L0, C0, C3, C4);" << endl;
01076     pg << "CALL 'castA(L1, C1, C3, C4);" << endl;
01077     pg << "CALL 'castA(L2, C2, C3, C4);" << endl;
01078     pg << "CALL 'castA(L3, C0, C3, C4);" << endl;
01079     pg << "CALL 'castA(L4, C1, C3, C4);" << endl;
01080     pg << "CALL 'castA(L5, C2, C3, C4);" << endl;
01081 
01082     pg << "CALL 'castA(L6, C0, C3, C5);" << endl;
01083     pg << "CALL 'castA(L7, C1, C3, C5);" << endl;
01084     pg << "CALL 'castA(L8, C2, C3, C5);" << endl;
01085     pg << "CALL 'castA(L9, C0, C3, C5);" << endl;
01086     pg << "CALL 'castA(L10, C1, C3, C5);" << endl;
01087     pg << "CALL 'castA(L11, C2, C3, C5);" << endl;
01088 
01089     pg << "CALL 'castA(L12, C0, C3, C6);" << endl;
01090     pg << "CALL 'castA(L13, C1, C3, C6);" << endl;
01091     pg << "CALL 'castA(L14, C2, C3, C6);" << endl;
01092     pg << "CALL 'castA(L15, C0, C3, C6);" << endl;
01093     pg << "CALL 'castA(L16, C1, C3, C6);" << endl;
01094     pg << "CALL 'castA(L17, C2, C3, C6);" << endl;
01095 
01096     refLocalOutput(pg, 18);      // make output available
01097 
01098     Calculator calc(0);
01099     try {
01100         calc.assemble(pg.str().c_str());
01101     } catch (FennelExcn& ex) {
01102         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01103         BOOST_MESSAGE(pg.str());
01104         BOOST_REQUIRE(0);
01105     }
01106 
01107     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01108     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01109     calc.bind(&inTuple, &outTuple);
01110     calc.exec();
01111     printOutput(outTuple, calc);
01112     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01113 
01114     // check results:
01115     // decimal(5,2)
01116     // -10.9 -> vc(3) = truncates
01117     BOOST_CHECK_EQUAL(iter->pc, 0);
01118     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01119     iter++;
01120 
01121     // -.09 -> vc(3) = truncates
01122     BOOST_CHECK_EQUAL(iter->pc, 1);
01123     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01124     iter++;
01125 
01126     // .30 - > vc(3) = ok
01127     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[2], ".30"));
01128 
01129     // -10.9 -> c(3) = truncates
01130     BOOST_CHECK_EQUAL(iter->pc, 3);
01131     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01132     iter++;
01133 
01134     // -.09 -> c(3) = truncates
01135     BOOST_CHECK_EQUAL(iter->pc, 4);
01136     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01137     iter++;
01138 
01139     // .30 - > c(3) = ok
01140     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[5], ".30"));
01141 
01142     // decimal(5,0)
01143     // -1090 -> vc(3) = truncates
01144     BOOST_CHECK_EQUAL(iter->pc, 6);
01145     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01146     iter++;
01147 
01148     // -9 -> vc(3) = ok
01149     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[7], "-9"));
01150 
01151     // 30 - > vc(3) = ok
01152     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[8], "30"));
01153 
01154     // -1090 -> c(3) = truncates
01155     BOOST_CHECK_EQUAL(iter->pc, 9);
01156     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01157     iter++;
01158 
01159     // -9 -> c(3) = ok
01160     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[10], "-9 "));
01161 
01162     // 30 - > c(3) = ok
01163     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[11], "30 "));
01164 
01165     // decimal(5,-2)
01166     // -109000 -> vc(3) = truncates
01167     BOOST_CHECK_EQUAL(iter->pc, 12);
01168     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01169     iter++;
01170 
01171     // -900 -> vc(3) = truncates
01172     BOOST_CHECK_EQUAL(iter->pc, 13);
01173     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01174     iter++;
01175 
01176     // 3000 -> vc(3) = truncates
01177     BOOST_CHECK_EQUAL(iter->pc, 14);
01178     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01179     iter++;
01180 
01181     // -109000 -> c(3) = truncates
01182     BOOST_CHECK_EQUAL(iter->pc, 15);
01183     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01184     iter++;
01185 
01186     // -900 -> c(3) = truncates
01187     BOOST_CHECK_EQUAL(iter->pc, 16);
01188     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01189     iter++;
01190 
01191     // 3000 -> c(3) = truncates
01192     BOOST_CHECK_EQUAL(iter->pc, 17);
01193     BOOST_CHECK_EQUAL(0, strcmp(iter->str, truncErr));
01194     iter++;
01195 
01196     BOOST_CHECK(iter == calc.mWarnings.end());
01197 }
01198 
01199 void CalcExtCastTest::testCalcExtCastCharToBoolean()
01200 {
01201     // test values: null, true, false, unknown, invalid; same with spaces.
01202     ostringstream pg(""), outloc("");
01203     outloc << "bo, bo, bo, bo, bo, bo, bo, bo;" << endl;
01204     pg << "O " << outloc.str();
01205     pg << "L " << outloc.str();
01206     pg << "C c,4, c,4, c,8, c,5, c,9, c,7, c,11, c,13;" << endl;
01207     pg << "V "                  // a null
01208        << ", 0x" << stringToHex("tRUe")
01209        << ", 0x" << stringToHex("  true  ")
01210        << ", 0x" << stringToHex("faLSe")
01211        << ", 0x" << stringToHex("  FALSE  ")
01212        << ", 0x" << stringToHex("UnknowN")
01213        << ", 0x" << stringToHex("  UnknowN  ")
01214        << ", 0x" << stringToHex("  Invalid    ")
01215        << ";" << endl;
01216     pg << "T;" << endl;
01217     for (int i = 0; i < 8; i++) {
01218         pg << "CALL 'castA(L"<<i<<",C"<<i<<");"<< endl;
01219     }
01220     refLocalOutput(pg, 8);      // make output available
01221 
01222     Calculator calc(0);
01223     try {
01224         calc.assemble(pg.str().c_str());
01225     } catch (FennelExcn& ex) {
01226         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01227         BOOST_MESSAGE(pg.str());
01228         BOOST_REQUIRE(0);
01229     }
01230 
01231     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01232     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01233     calc.bind(&inTuple, &outTuple);
01234     calc.exec();
01235     printOutput(outTuple, calc);
01236     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01237 
01238     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[0]));
01239     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[1], true));
01240     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[2], true));
01241     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[3], false));
01242     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[4], false));
01243 
01244     // TODO: SQL2003 says 'unknown' should be treated as null
01245     // For now, unknown -> bool = invalid char
01246     BOOST_CHECK_EQUAL(iter->pc, 5);
01247     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01248     iter++;
01249 
01250     BOOST_CHECK_EQUAL(iter->pc, 6);
01251     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01252     iter++;
01253 
01254     // invalid -> bool = invalid char
01255     BOOST_CHECK_EQUAL(iter->pc, 7);
01256     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01257     iter++;
01258 
01259     BOOST_CHECK(iter == calc.mWarnings.end());
01260 }
01261 
01262 void CalcExtCastTest::testCalcExtCastVarCharToBoolean()
01263 {
01264     // test values: null, true, false, unknown, invalid; same with spaces.
01265     ostringstream pg(""), outloc("");
01266     outloc << "bo, bo, bo, bo, bo, bo, bo, bo;" << endl;
01267     pg << "O " << outloc.str();
01268     pg << "L " << outloc.str();
01269     pg << "C vc,4, vc,8, vc,8, vc,9, vc,9, vc,7, vc,11, vc,13;" << endl;
01270     pg << "V "                  // a null
01271        << ", 0x" << stringToHex("tRUe")
01272        << ", 0x" << stringToHex("  true  ")
01273        << ", 0x" << stringToHex("faLSe")
01274        << ", 0x" << stringToHex("  FALSE  ")
01275        << ", 0x" << stringToHex("UnknowN")
01276        << ", 0x" << stringToHex("  UnknowN  ")
01277        << ", 0x" << stringToHex("  Invalid    ")
01278        << ";" << endl;
01279     pg << "T;" << endl;
01280     for (int i = 0; i < 8; i++) {
01281         pg << "CALL 'castA(L" << i << ",C" << i << ");" << endl;
01282     }
01283     refLocalOutput(pg, 8);      // make output available
01284 
01285     Calculator calc(0);
01286     try {
01287         calc.assemble(pg.str().c_str());
01288     } catch (FennelExcn& ex) {
01289         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01290         BOOST_MESSAGE(pg.str());
01291         BOOST_REQUIRE(0);
01292     }
01293 
01294     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01295     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01296     calc.bind(&inTuple, &outTuple);
01297     calc.exec();
01298     printOutput(outTuple, calc);
01299     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01300 
01301     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[0]));
01302     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[1], true));
01303     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[2], true));
01304     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[3], false));
01305     BOOST_CHECK_EQUAL(1, cmpTupBool(outTuple[4], false));
01306 
01307     // TODO: SQL2003 says 'unknown' should be treated as null
01308     // For now, unknown -> bool = invalid char
01309     BOOST_CHECK_EQUAL(iter->pc, 5);
01310     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01311     iter++;
01312 
01313     BOOST_CHECK_EQUAL(iter->pc, 6);
01314     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01315     iter++;
01316 
01317     // invalid -> bool = invalid char
01318     BOOST_CHECK_EQUAL(iter->pc, 7);
01319     BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01320     iter++;
01321 
01322     BOOST_CHECK(iter == calc.mWarnings.end());
01323 }
01324 
01325 
01326 void CalcExtCastTest::testCalcExtCastVarCharToExact()
01327 {
01328     // test values: null; 123, -123, MAX and MIN; same with trailing spaces.
01329     ostringstream pg(""), outloc("");
01330     outloc << "s8, s8, s8, s8, s8, s8, s8, s8, s8;" << endl;
01331     pg << "O " << outloc.str();
01332     pg << "L " << outloc.str();
01333     pg << "C vc,4, vc,4, vc,4, vc,20, vc,21, vc,8, vc,8, vc,32, vc,32;" << endl;
01334     pg << "V "                  // a null
01335        << ", 0x" << stringToHex("123") << ", 0x" << stringToHex("-123")
01336        << ", 0x" << stringToHex(maxInt64String())
01337        << ", 0x" << stringToHex(minInt64String())
01338        << ", 0x" << stringToHex("123     ") << ", 0x" << stringToHex("-123    ")
01339        << ", 0x" << stringToHex(rpad(maxInt64String(), 32))
01340        << ", 0x" << stringToHex(rpad(minInt64String(), 32))
01341        << ";" << endl;
01342     pg << "T;" << endl;
01343     for (int i = 0; i < 9; i++) {
01344         pg << "CALL 'castA(L" << i << ",C" << i << ");" << endl;
01345     }
01346     refLocalOutput(pg, 9);      // make output available
01347 
01348     Calculator calc(0);
01349     try {
01350         calc.assemble(pg.str().c_str());
01351     } catch (FennelExcn& ex) {
01352         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01353         BOOST_MESSAGE(pg.str());
01354         BOOST_REQUIRE(0);
01355     }
01356 
01357     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01358     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01359     calc.bind(&inTuple, &outTuple);
01360     calc.exec();
01361     printOutput(outTuple, calc);
01362     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01363 
01364     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[0]));
01365     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[1],  123));
01366     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[2], -123));
01367     BOOST_CHECK_EQUAL(
01368         0, cmpTupInt64(outTuple[3], numeric_limits<int64_t>::max()));
01369     BOOST_CHECK_EQUAL(
01370         0, cmpTupInt64(outTuple[4], numeric_limits<int64_t>::min()));
01371     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[5],  123));
01372     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[6], -123));
01373     BOOST_CHECK_EQUAL(
01374         0, cmpTupInt64(outTuple[7], numeric_limits<int64_t>::max()));
01375     BOOST_CHECK_EQUAL(
01376         0, cmpTupInt64(outTuple[8], numeric_limits<int64_t>::min()));
01377     BOOST_CHECK(iter == calc.mWarnings.end());
01378 }
01379 
01380 void CalcExtCastTest::testCalcExtCastCharToExact()
01381 {
01382     // test values: null; 123, -123, MAX and MIN; same with trailing spaces.
01383     ostringstream pg(""), outloc("");
01384     outloc << "s8, s8, s8, s8, s8, s8, s8, s8, s8;" << endl;
01385     pg << "O " << outloc.str();
01386     pg << "L " << outloc.str();
01387     pg << "C c,3, c,3, c,4, c,19, c,20, c,8, c,8, c,32, c,32;" << endl;
01388     pg << "V "                  // a null
01389        << ", 0x" << stringToHex("123") << ", 0x" << stringToHex("-123")
01390        << ", 0x" << stringToHex(maxInt64String())
01391        << ", 0x" << stringToHex(minInt64String())
01392        << ", 0x" << stringToHex("123     ") << ", 0x" << stringToHex("-123    ")
01393        << ", 0x" << stringToHex(rpad(maxInt64String(), 32))
01394        << ", 0x" << stringToHex(rpad(minInt64String(), 32))
01395        << ";" << endl;
01396     pg << "T;" << endl;
01397     for (int i = 0; i < 9; i++) {
01398         pg << "CALL 'castA(L" << i << ",C" << i << ");" << endl;
01399     }
01400     refLocalOutput(pg, 9);      // make output available
01401 
01402     Calculator calc(0);
01403     try {
01404         calc.assemble(pg.str().c_str());
01405     } catch (FennelExcn& ex) {
01406         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01407         BOOST_MESSAGE(pg.str());
01408         BOOST_REQUIRE(0);
01409     }
01410 
01411     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01412     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01413     calc.bind(&inTuple, &outTuple);
01414     calc.exec();
01415     printOutput(outTuple, calc);
01416     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01417 
01418     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[0]));
01419     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[1],  123));
01420     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[2], -123));
01421     BOOST_CHECK_EQUAL(
01422         0, cmpTupInt64(outTuple[3], numeric_limits<int64_t>::max()));
01423     BOOST_CHECK_EQUAL(
01424         0, cmpTupInt64(outTuple[4], numeric_limits<int64_t>::min()));
01425     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[5],  123));
01426     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[6], -123));
01427     BOOST_CHECK_EQUAL(
01428         0, cmpTupInt64(outTuple[7], numeric_limits<int64_t>::max()));
01429     BOOST_CHECK_EQUAL(
01430         0, cmpTupInt64(outTuple[8], numeric_limits<int64_t>::min()));
01431     BOOST_CHECK(iter == calc.mWarnings.end());
01432 }
01433 
01434 void CalcExtCastTest::testCalcExtCastVarCharToDecimal()
01435 {
01436     // test values: null, 99.99, -105.0e-3, 950.00, 234.446
01437     // same with trailing spaces.to
01438     // decimal(5, 2)
01439     // decimal(5, 0)
01440     // decimal(5, -2)
01441     ostringstream pg(""), outloc("");
01442     outloc << "s8, s8, s8, s8, s8, s8, s8, s8, s8, "
01443            << "s8, s8, s8, s8, s8, s8, s8, s8, s8, "
01444            << "s8, s8, s8, s8, s8, s8, s8, s8, s8;"
01445            << endl;
01446     pg << "O " << outloc.str();
01447     pg << "L " << outloc.str();
01448     pg << "C vc,1, vc,5, vc,9, vc,6, vc,7, vc,10, vc,10, vc,10, vc,10, "
01449        << "  s4, s4, s4, s4;" << endl;
01450     pg << "V "                  // a null
01451        << ", 0x" << stringToHex("99.99")
01452        << ", 0x" << stringToHex("-105.0e-3")
01453        << ", 0x" << stringToHex("950.00")
01454        << ", 0x" << stringToHex("234.446")
01455        << ", 0x" << stringToHex("99.99     ")
01456        << ", 0x" << stringToHex("-105.0e-3 ")
01457        << ", 0x" << stringToHex("950.00    ")
01458        << ", 0x" << stringToHex("234.446   ")
01459        << ", 5, 2, 0, -2;" << endl;
01460     pg << "T;" << endl;
01461 
01462     for (int i = 0; i < 9; i++) {
01463         pg << "CALL 'castA(L" << i << ",C" << i << ",C9, C10);" << endl;
01464     }
01465     for (int i = 0; i < 9; i++) {
01466         pg << "CALL 'castA(L" << (i + 9) << ",C" << i << ",C9, C11);" << endl;
01467     }
01468     for (int i = 0; i < 9; i++) {
01469         pg << "CALL 'castA(L" << (i + 18) << ",C" << i << ",C9, C12);" << endl;
01470     }
01471     refLocalOutput(pg, 9*3);      // make output available
01472 
01473     Calculator calc(0);
01474     try {
01475         calc.assemble(pg.str().c_str());
01476     } catch (FennelExcn& ex) {
01477         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01478         BOOST_MESSAGE(pg.str());
01479         BOOST_REQUIRE(0);
01480     }
01481 
01482     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01483     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01484     calc.bind(&inTuple, &outTuple);
01485     calc.exec();
01486     printOutput(outTuple, calc);
01487     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01488 
01489     // decimal(5,2)
01490     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[0]));
01491     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[1],  9999));
01492     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[2],  -11));
01493     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[3],  95000));
01494     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[4],  23445));
01495     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[5],  9999));
01496     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[6],  -11));
01497     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[7],  95000));
01498     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[8],  23445));
01499 
01500     // decimal(5,0)
01501     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[9]));
01502     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[10],  100));
01503     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[11],  0));
01504     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[12],  950));
01505     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[13],  234));
01506     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[14],  100));
01507     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[15],  0));
01508     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[16],  950));
01509     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[17],  234));
01510 
01511     // decimal(5,-2)
01512     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[18]));
01513     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[19],  1));
01514     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[20],  0));
01515     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[21],  10));
01516     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[22],  2));
01517     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[23],  1));
01518     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[24],  0));
01519     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[25],  10));
01520     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[26],  2));
01521 
01522     BOOST_CHECK(iter == calc.mWarnings.end());
01523 }
01524 
01525 void CalcExtCastTest::testCalcExtCastCharToDecimal()
01526 {
01527     // test values: null, .8987, -0005.2, +980, 0.000000000000355e14
01528     // same with trailing spaces.to
01529     // decimal(5, 2)
01530     // decimal(5, 0)
01531     // decimal(5, -2)
01532     ostringstream pg(""), outloc("");
01533     outloc << "s8, s8, s8, s8, s8, s8, s8, s8, s8, "
01534            << "s8, s8, s8, s8, s8, s8, s8, s8, s8, "
01535            << "s8, s8, s8, s8, s8, s8, s8, s8, s8;"
01536            << endl;
01537     pg << "O " << outloc.str();
01538     pg << "L " << outloc.str();
01539     pg << "C c,1, c,5, c,7, c,4, c,20, c,10, c,10, c,10, c,32, "
01540        << "  s4, s4, s4, s4;" << endl;
01541     pg << "V "                  // a null
01542        << ", 0x" << stringToHex(".8987")
01543        << ", 0x" << stringToHex("-0005.2")
01544        << ", 0x" << stringToHex("+980")
01545        << ", 0x" << stringToHex("0.000000000000355e14")
01546        << ", 0x" << stringToHex(".8987     ")
01547        << ", 0x" << stringToHex("-0005.2   ")
01548        << ", 0x" << stringToHex("+980      ")
01549        << ", 0x" << stringToHex("0.000000000000355e14            ")
01550        << ", 5, 2, 0, -2;" << endl;
01551     pg << "T;" << endl;
01552 
01553     for (int i = 0; i < 9; i++) {
01554         pg << "CALL 'castA(L" << i << ",C" << i << ",C9, C10);" <<  endl;
01555     }
01556     for (int i = 0; i < 9; i++) {
01557         pg << "CALL 'castA(L" << (i + 9) << ",C" << i << ",C9, C11);" << endl;
01558     }
01559     for (int i = 0; i < 9; i++) {
01560         pg << "CALL 'castA(L" << (i + 18) << ",C" << i << ",C9, C12);" << endl;
01561     }
01562     refLocalOutput(pg, 9*3);      // make output available
01563 
01564     Calculator calc(0);
01565     try {
01566         calc.assemble(pg.str().c_str());
01567     } catch (FennelExcn& ex) {
01568         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01569         BOOST_MESSAGE(pg.str());
01570         BOOST_REQUIRE(0);
01571     }
01572 
01573     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01574     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01575     calc.bind(&inTuple, &outTuple);
01576     calc.exec();
01577     printOutput(outTuple, calc);
01578     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01579 
01580     // decimal(5,2)
01581     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[0]));
01582     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[1],  90));
01583     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[2],  -520));
01584     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[3],  98000));
01585     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[4],  3550));
01586     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[5],  90));
01587     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[6],  -520));
01588     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[7],  98000));
01589     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[8],  3550));
01590 
01591     // decimal(5,0)
01592     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[9]));
01593     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[10],  1));
01594     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[11],  -5));
01595     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[12],  980));
01596     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[13],  36));
01597     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[14],  1));
01598     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[15],  -5));
01599     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[16],  980));
01600     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[17],  36));
01601 
01602     // decimal(5,-2)
01603     BOOST_CHECK_EQUAL(1, cmpTupNull(outTuple[18]));
01604     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[19],  0));
01605     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[20],  0));
01606     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[21],  10));
01607     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[22],  0));
01608     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[23],  0));
01609     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[24],  0));
01610     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[25],  10));
01611     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[26],  0));
01612 
01613     BOOST_CHECK(iter == calc.mWarnings.end());
01614 }
01615 
01616 void CalcExtCastTest::testCalcExtCastStringToExactFails()
01617 {
01618     // test invalid values abc, 12z
01619     ostringstream pg(""), outloc("");
01620     outloc << "s8, s8, s8, s8;" << endl;
01621     pg << "O " << outloc.str();
01622     pg << "L " << outloc.str();
01623     pg << "C vc,3, vc,3, c,3, c,3;" << endl;
01624     pg << "V 0x" << stringToHex("abc") << ", 0x" << stringToHex("12z")
01625        << ", 0x" << stringToHex("abc") << ", 0x" << stringToHex("12z")
01626        << ";" << endl;
01627     pg << "T;" << endl;
01628     pg << "CALL 'castA(L0, C0);" << endl;
01629     pg << "CALL 'castA(L1, C1);" << endl;
01630     pg << "CALL 'castA(L2, C0);" << endl;
01631     pg << "CALL 'castA(L3, C1);" << endl;
01632     refLocalOutput(pg, 4);      // make output available
01633 
01634     Calculator calc(0);
01635     try {
01636         calc.assemble(pg.str().c_str());
01637     } catch (FennelExcn& ex) {
01638         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01639         BOOST_MESSAGE(pg.str());
01640         BOOST_REQUIRE(0);
01641     }
01642 
01643     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01644     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01645     calc.bind(&inTuple, &outTuple);
01646     calc.exec();
01647     printOutput(outTuple, calc);
01648 
01649     // all the casts should have failed
01650     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01651     for (int pc = 0; pc < 4; pc++, iter++) {
01652         BOOST_CHECK_EQUAL(iter->pc, pc);
01653         BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01654     }
01655     BOOST_CHECK(iter == calc.mWarnings.end());
01656 }
01657 
01658 void CalcExtCastTest::testCalcExtCastStringToDecimalFails()
01659 {
01660     // test invalid values: 12c, 34.54.243, 342.342e453.23, 234e 23
01661     // cast to decimal(5,2)
01662     ostringstream pg(""), outloc("");
01663     outloc << "s8, s8, s8, s8, s8, s8, s8, s8;" << endl;
01664     pg << "O " << outloc.str();
01665     pg << "L " << outloc.str();
01666     pg << "C vc,3, vc,9, vc,14, vc,7, c,3, c,9, c,14, c,7, "
01667        << "  s4, s4;" << endl;
01668     pg << "V 0x" << stringToHex("12c")
01669        << ", 0x" << stringToHex("34.54.243")
01670        << ", 0x" << stringToHex("342.342e453.23")
01671        << ", 0x" << stringToHex("234e 23")
01672        << ", 0x" << stringToHex("12c")
01673        << ", 0x" << stringToHex("34.54.243")
01674        << ", 0x" << stringToHex("342.342e453.23")
01675        << ", 0x" << stringToHex("234e 23")
01676        << ", 5, 2;" << endl;
01677     pg << "T;" << endl;
01678 
01679     for (int i = 0; i < 8; i++) {
01680         pg << "CALL 'castA(L" << i << ",C" << i << ",C8, C9);" << endl;
01681     }
01682     refLocalOutput(pg, 8);      // make output available
01683 
01684     Calculator calc(0);
01685     try {
01686         calc.assemble(pg.str().c_str());
01687     } catch (FennelExcn& ex) {
01688         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01689         BOOST_MESSAGE(pg.str());
01690         BOOST_REQUIRE(0);
01691     }
01692 
01693     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01694     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01695     calc.bind(&inTuple, &outTuple);
01696     calc.exec();
01697     printOutput(outTuple, calc);
01698 
01699     // all the casts should have failed
01700     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01701     for (int pc = 0; pc < 8; pc++, iter++) {
01702         BOOST_CHECK_EQUAL(iter->pc, pc);
01703         BOOST_CHECK_EQUAL(0, strcmp(iter->str, invalidCharErr));
01704     }
01705     BOOST_CHECK(iter == calc.mWarnings.end());
01706 }
01707 
01708 void CalcExtCastTest::testCalcExtCastStringToDecimalMinMax()
01709 {
01710     // test values: MIN, MAX,
01711     //              9223372036854775808 (MAX+1),
01712     //              9223372036854775807.12345
01713     //              9223372036854775807.9
01714     //              -9223372036854775809
01715     //              -9223372036854775807.9
01716     //              -9223372036854775808.9
01717     //              9323415432153452535
01718     //              9.78E+18
01719     //              9.78E+20
01720     // cast to decimal(19, 0)
01721     // cast to decimal(9, -10)
01722     ostringstream pg(""), outloc("");
01723     outloc << "s8, s8, s8, s8, s8, s8, s8, s8, s8, s8, s8, "
01724            << "s8, s8, s8, s8, s8, s8, s8, s8, s8, s8, s8;" << endl;
01725     pg << "O " << outloc.str();
01726     pg << "L " << outloc.str();
01727     pg << "C vc,30, vc,30, vc,30, vc,30, vc,30, "
01728        << "  vc,30, vc,30, vc,30, vc,30, vc,30, vc,30, "
01729        << "  s4, s4, s4, s4;" << endl;
01730     pg << "V 0x" << stringToHex(minInt64String())
01731        << ", 0x" << stringToHex(maxInt64String())
01732        << ", 0x" << stringToHex("9223372036854775808")
01733        << ", 0x" << stringToHex("9223372036854775807.12345")
01734        << ", 0x" << stringToHex("9223372036854775807.9")
01735        << ", 0x" << stringToHex("-9223372036854775809")
01736        << ", 0x" << stringToHex("-9223372036854775807.9")
01737        << ", 0x" << stringToHex("-9223372036854775808.9")
01738        << ", 0x" << stringToHex("9323415432153452535")
01739        << ", 0x" << stringToHex("9.78E+18")
01740        << ", 0x" << stringToHex("9.78E+20")
01741        << ", 19, 0, 9, -10;" << endl;
01742     pg << "T;" << endl;
01743 
01744     for (int i = 0; i < 11; i++) {
01745         pg << "CALL 'castA(L" << i << ",C" << i << ",C11, C12);" << endl;
01746     }
01747     for (int i = 0; i < 11; i++) {
01748         pg << "CALL 'castA(L" << (i + 11) << ",C" << i << ",C13, C14);" << endl;
01749     }
01750     refLocalOutput(pg, 22);      // make output available
01751 
01752     Calculator calc(0);
01753     try {
01754         calc.assemble(pg.str().c_str());
01755     } catch (FennelExcn& ex) {
01756         cout << ex.getMessage();
01757         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01758         BOOST_MESSAGE(pg.str());
01759         BOOST_REQUIRE(0);
01760     }
01761 
01762     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01763     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01764     calc.bind(&inTuple, &outTuple);
01765     calc.exec();
01766     printOutput(outTuple, calc);
01767 
01768     // check results:
01769     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01770 
01771     // decimal(19,0)
01772     // MIN -> decimal(19,0) = ok
01773     BOOST_CHECK_EQUAL(
01774         0, cmpTupInt64(outTuple[0], std::numeric_limits<int64_t>::min()));
01775 
01776     // MAX -> decimal(19,0) = ok
01777     BOOST_CHECK_EQUAL(
01778         0, cmpTupInt64(outTuple[1], std::numeric_limits<int64_t>::max()));
01779 
01780     // MAX + 1 -> decimal(19,0) = out of range
01781     BOOST_CHECK_EQUAL(iter->pc, 2);
01782     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01783     iter++;
01784 
01785     // MAX.12345 -> decimal(19, 0) = ok
01786     BOOST_CHECK_EQUAL(
01787         0, cmpTupInt64(outTuple[3], std::numeric_limits<int64_t>::max()));
01788 
01789     // MAX.9 -> decimal(19, 0) = out of range
01790     BOOST_CHECK_EQUAL(iter->pc, 4);
01791     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01792     iter++;
01793 
01794     // MIN - 1 -> decimal(19,0) = out of range
01795     BOOST_CHECK_EQUAL(iter->pc, 5);
01796     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01797     iter++;
01798 
01799     // (MIN+1).9 -> decimal(19,0) = ok
01800     BOOST_CHECK_EQUAL(
01801         0, cmpTupInt64(outTuple[6], std::numeric_limits<int64_t>::min()));
01802 
01803     // MIN.9 -> decimal(19,0) = out of range
01804     BOOST_CHECK_EQUAL(iter->pc, 7);
01805     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01806     iter++;
01807 
01808     // 9323415432153452535 -> decimal(19,0) = out of range
01809     BOOST_CHECK_EQUAL(iter->pc, 8);
01810     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01811     iter++;
01812 
01813     // 9.78E+18 -> decimal(19,0) = out of range
01814     BOOST_CHECK_EQUAL(iter->pc, 9);
01815     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01816     iter++;
01817 
01818     // 9.78E+20 -> decimal(19,0) = out of range
01819     BOOST_CHECK_EQUAL(iter->pc, 10);
01820     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01821     iter++;
01822 
01823     // decimal(9,-10)
01824     int64_t factor = 1;
01825     for (int i = 0; i < 10; i++) {
01826         factor *= 10;
01827     }
01828     int64_t smax = std::numeric_limits<int64_t>::max()/factor + 1;
01829     int64_t smin = std::numeric_limits<int64_t>::min()/factor - 1;
01830 
01831     // MIN -> decimal(9,-10) = ok
01832     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[11], smin));
01833 
01834     // MAX -> decimal(9,-10) = ok
01835     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[12], smax));
01836 
01837     // MAX + 1 -> decimal(9,-10) = ok
01838     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[13], smax));
01839 
01840     // MAX.12345 -> decimal(19,-10) = ok
01841     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[14], smax));
01842 
01843     // MAX.9 -> decimal(19,-10) = ok
01844     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[15], smax));
01845 
01846     // MIN - 1 -> decimal(9,-10) = ok
01847     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[16], smin));
01848 
01849     // (MIN+1).9 -> decimal(9,-10) = ok
01850     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[17], smin));
01851 
01852     // MIN.9 -> decimal(9,-10) = ok
01853     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[18], smin));
01854 
01855     // 9323415432153452535 -> decimal(9,-10) = ok
01856     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[19], 932341543ll));
01857 
01858     // 9.78E+18 -> decimal(9,-10) = ok
01859     BOOST_CHECK_EQUAL(0, cmpTupInt64(outTuple[20], 978000000ll));
01860 
01861     // 9.78E+20 -> decimal(9,-10) = out of range
01862     BOOST_CHECK_EQUAL(iter->pc, 21);
01863     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01864     iter++;
01865 
01866     BOOST_CHECK(iter == calc.mWarnings.end());
01867 }
01868 
01869 
01870 void CalcExtCastTest::testCalcExtCastStringToDecimalRange()
01871 {
01872     // test values: 1000 999.999, 999.991 9.99999e2 9.9999e2,
01873     // 99999999990000000000e-20, cast to decimal(5, 2)
01874     ostringstream pg(""), outloc("");
01875     outloc << "s8, s8, s8, s8, s8, s8;" << endl;
01876     pg << "O " << outloc.str();
01877     pg << "L " << outloc.str();
01878     pg << "C vc,30, vc,30, vc,30, vc,30, vc,30, vc,30, "
01879        << "  s4, s4;" << endl;
01880     pg << "V 0x" << stringToHex("1000")
01881        << ", 0x" << stringToHex("999.999")
01882        << ", 0x" << stringToHex("999.991")
01883        << ", 0x" << stringToHex("9.99999e2")
01884        << ", 0x" << stringToHex("9.9999e2")
01885        << ", 0x" << stringToHex("99999999990000000000e-20")
01886        << ", 5, 2;" << endl;
01887     pg << "T;" << endl;
01888 
01889     for (int i = 0; i < 6; i++) {
01890         pg << "CALL 'castA(L" << i << ",C" << i << ",C6, C7);" << endl;
01891     }
01892     refLocalOutput(pg, 6);      // make output available
01893 
01894     Calculator calc(0);
01895     try {
01896         calc.assemble(pg.str().c_str());
01897     } catch (FennelExcn& ex) {
01898         cout << ex.getMessage();
01899         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01900         BOOST_MESSAGE(pg.str());
01901         BOOST_REQUIRE(0);
01902     }
01903 
01904     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01905     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01906     calc.bind(&inTuple, &outTuple);
01907     calc.exec();
01908     printOutput(outTuple, calc);
01909 
01910     // check results:
01911     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
01912 
01913     // decimal(5,2)
01914     // 1000 -> decimal(5,2) = out of range
01915     BOOST_CHECK_EQUAL(iter->pc, 0);
01916     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01917     iter++;
01918 
01919     // 999.999 -> decimal(5,2) = out of range
01920     BOOST_CHECK_EQUAL(iter->pc, 1);
01921     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01922     iter++;
01923 
01924     // 999.991 -> decimal(5,2) = ok
01925     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[2], 99999));
01926 
01927     // 9.99999e2 -> decimal(5,2) = out of range
01928     BOOST_CHECK_EQUAL(iter->pc, 3);
01929     BOOST_CHECK_EQUAL(0, strcmp(iter->str, outOfRangeErr));
01930     iter++;
01931 
01932     // 9.9999e2 -> decimal(5,2) = ok
01933     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[4], 99999));
01934 
01935     // 99999999990000000000e-20 -> decimal(5,2) = ok
01936     BOOST_CHECK_EQUAL(0, cmpTupInt(outTuple[5], 100));
01937     BOOST_CHECK(iter == calc.mWarnings.end());
01938 }
01939 
01940 
01941 void CalcExtCastTest::testCalcExtCastStringToApprox()
01942 {
01943     // test values: null, 0, 0.0, .0, 1.98, -1.98, 0.001, 0.00100
01944     // as varchar(8), as trim chars, and as char(16).
01945     ostringstream pg(""), outloc("");
01946     outloc << "d, d, d, d, d, d, d, d, "
01947            << "d, d, d, d, d, d, d, d, "
01948            << "d, d, d, d, d, d, d, d;" << endl;
01949     pg << "O " << outloc.str();
01950     pg << "L " << outloc.str();
01951     pg << "C "
01952        << "vc,8, vc,8, vc,8, vc,8, vc,8, vc,8, vc,8, vc,8, "
01953        << "c,1, c,1, c,3, c,2, c,4, c,5, c,5, c,7, "
01954        << "c,16, c,16, c,16, c,16, c,16, c,16, c,16, c,16;" << endl;
01955     pg << "V ";
01956     for (int i = 0; i < 2; i++) {
01957         pg << ","
01958            << "0x" << stringToHex("0")       << ","
01959            << "0x" << stringToHex("0.0")     << ","
01960            << "0x" << stringToHex(".0")      << ","
01961            << "0x" << stringToHex("1.98")    << ","
01962            << "0x" << stringToHex("-1.98")   << ","
01963            << "0x" << stringToHex("0.001")   << ","
01964            << "0x" << stringToHex("0.00100") << ",";
01965     }
01966     // same values padded to char(16)
01967     pg << ","
01968        << "0x" << stringToHex("0               ") << ","
01969        << "0x" << stringToHex("0.0             ") << ","
01970        << "0x" << stringToHex(".0              ") << ","
01971        << "0x" << stringToHex("1.98            ") << ","
01972        << "0x" << stringToHex("-1.98           ") << ","
01973        << "0x" << stringToHex("0.001           ") << ","
01974        << "0x" << stringToHex("0.00100         ") << ";" << endl;
01975     pg << "T;" << endl;
01976     for (int i = 0; i < 8; i++) {
01977         pg << "CALL 'castA(L" << i << ", C" << i << ");" << endl;
01978     }
01979     for (int i = 0; i < 8; i++) {
01980         pg << "CALL 'castA(L" << (i + 8) << ", C" << i << ");" << endl;
01981     }
01982     for (int i = 0; i < 8; i++) {
01983         pg << "CALL 'castA(L" << (i + 16) << ", C" << i << ");" << endl;
01984     }
01985     refLocalOutput(pg, 24);     // make output available
01986 
01987     Calculator calc(0);
01988     try {
01989         calc.assemble(pg.str().c_str());
01990     } catch (FennelExcn& ex) {
01991         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
01992         BOOST_MESSAGE(pg.str());
01993         BOOST_REQUIRE(0);
01994     }
01995 
01996     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
01997     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
01998     calc.bind(&inTuple, &outTuple);
01999     calc.exec();
02000     printOutput(outTuple, calc);
02001 
02002     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
02003     // check 3 identical sets of 8 values
02004     for (int pass = 0, i = 0; pass < 3; pass++) {
02005         BOOST_CHECK(cmpTupNull(outTuple[i++]));
02006         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], 0));
02007         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], 0));
02008         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], 0));
02009         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], 1.98));
02010         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], -1.98));
02011         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], 0.001));
02012         BOOST_CHECK_EQUAL(0, cmpTupDouble(outTuple[i++], 0.001));
02013     }
02014     BOOST_CHECK(iter == calc.mWarnings.end());
02015 }
02016 
02017 void CalcExtCastTest::testCalcExtCastApproxToString()
02018 {
02019     // double test values: null, 0, +1.98, -1.98, +0.001, -0.001
02020 
02021     ostringstream pg(""), outloc("");
02022     outloc << "vc,16, vc,16, vc,16, vc,16, vc,16, vc,16, "
02023            << "c,16, c,16, c,16, c,16, c,16, c,16;" << endl;
02024     pg << "O " << outloc.str();
02025     pg << "L " << outloc.str();
02026     pg << "C d,d,d,d,d,d;" << endl;
02027     pg << "V , 0.0, 1.98, -1.98, 0.001, -0.001;" << endl;
02028     pg << "T;" << endl;
02029     for (int i = 0; i < 6; i++) {
02030         pg << "CALL 'castA(L" << i << ", C" << i << ");" << endl;
02031     }
02032     for (int i = 0; i < 6; i++) {
02033         pg << "CALL 'castA(L" << (i + 6) << ", C" << i << ");" << endl;
02034     }
02035     refLocalOutput(pg, 12);     // make output available
02036     // cerr << "testCalcExtCastApproxToString Program:\n" << pg.str() << endl;
02037 
02038     Calculator calc(0);
02039     try {
02040         calc.assemble(pg.str().c_str());
02041     } catch (FennelExcn& ex) {
02042         BOOST_MESSAGE("Assemble exception " << ex.getMessage());
02043         BOOST_MESSAGE(pg.str());
02044         BOOST_REQUIRE(0);
02045     }
02046 
02047     TupleDataWithBuffer outTuple(calc.getOutputRegisterDescriptor());
02048     TupleDataWithBuffer inTuple(calc.getInputRegisterDescriptor());
02049     calc.bind(&inTuple, &outTuple);
02050     calc.exec();
02051     printOutput(outTuple, calc);
02052 
02053     deque<CalcMessage>::iterator iter = calc.mWarnings.begin();
02054 
02055     int i = 0;
02056     // first the varchars
02057     // TODO: fix these strings when calc/SqlString produces terser results.
02058     BOOST_CHECK(cmpTupNull(outTuple[i++]));
02059     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "0E0"));
02060     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "1.98E0"));
02061     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "-1.98E0"));
02062     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "1E-3"));
02063     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "-1E-3"));
02064     // then the char(16)s
02065     BOOST_CHECK(cmpTupNull(outTuple[i++]));
02066     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "0E0             "));
02067     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "1.98E0          "));
02068     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "-1.98E0         "));
02069     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "1E-3            "));
02070     BOOST_CHECK_EQUAL(0, cmpTupStr(outTuple[i++], "-1E-3           "));
02071     BOOST_CHECK(iter == calc.mWarnings.end());
02072 }
02073 
02074 FENNEL_UNIT_TEST_SUITE(CalcExtCastTest);
02075 
02076 // End CalcExtCastTest.cpp

Generated on Mon Jun 22 04:00:13 2009 for Fennel by  doxygen 1.5.1