You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-31 18:30:33 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			386 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (C) 2014 InfiniDB, Inc.
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU General Public License
 | |
|    as published by the Free Software Foundation; version 2 of
 | |
|    the License.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | |
|    MA 02110-1301, USA. */
 | |
| 
 | |
| /**
 | |
| * $Id$
 | |
| */
 | |
| 
 | |
| #include <iostream>
 | |
| #include <string>
 | |
| using namespace std;
 | |
| 
 | |
| #include <cppunit/extensions/HelperMacros.h>
 | |
| 
 | |
| #include "dataconvert.h"
 | |
| #include "funchelpers.h"
 | |
| using namespace funcexp;
 | |
| using namespace dataconvert;
 | |
| #define MAX_DAY_NUMBER 3652424L
 | |
| 
 | |
| #include "functioncolumn.h"
 | |
| #include "intervalcolumn.h"
 | |
| using namespace execplan;
 | |
| 
 | |
| #include "timeextract.h"
 | |
| 
 | |
| class FuncExpTest : public CppUnit::TestFixture
 | |
| {
 | |
| 
 | |
|     CPPUNIT_TEST_SUITE( FuncExpTest );
 | |
| 
 | |
|     CPPUNIT_TEST( fe_getnumbertest );
 | |
|     CPPUNIT_TEST( fe_strtodatetest );
 | |
|     CPPUNIT_TEST( fe_dateaddtest );
 | |
|     CPPUNIT_TEST( fe_daynametest );
 | |
|     CPPUNIT_TEST( fe_fromunixtimetest );
 | |
|     CPPUNIT_TEST_SUITE_END();
 | |
| 
 | |
| private:
 | |
| 
 | |
| public:
 | |
|     void setUp()
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void tearDown()
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void show_datetime_debugs( const string& nm, const DateTime& d1 )
 | |
|     {
 | |
|         cout << nm << ".day     = " << setw(10) << d1.day << endl;
 | |
|         cout << nm << ".month   = " << setw(10) << d1.month << endl;
 | |
|         cout << nm << ".year    = " << setw(10) << d1.year << endl;
 | |
|         cout << nm << ".hour    = " << setw(10) << d1.hour << endl;
 | |
|         cout << nm << ".minute  = " << setw(10) << d1.minute << endl;
 | |
|         cout << nm << ".second  = " << setw(10) << d1.second <<  endl;
 | |
|         cout << nm << ".msecond = " << setw(10) << d1.msecond << endl;
 | |
|     }
 | |
| 
 | |
|     void fe_strtodatetest()
 | |
|     {
 | |
|         struct DateCheck
 | |
|         {
 | |
|             const char* inputstr;
 | |
|             const char* formatstr;
 | |
|             DateTime    date;
 | |
|         };
 | |
| 
 | |
|         DateCheck date_tests[] =
 | |
|         {
 | |
|             { "2009", "%Y", DateTime(2009, 0, 0, 0, 0, 0, 0) },
 | |
|             { "     2009", "%Y", DateTime(2009, 0, 0, 0, 0, 0, 0) },
 | |
|             { "     2009", "  %Y", DateTime(2009, 0, 0, 0, 0, 0, 0) },
 | |
|             { "jan", "%b", DateTime(0, 1, 0, 0, 0, 0, 0) },
 | |
|             { "2009feb", "%Y%b", DateTime(2009, 2, 0, 0, 0, 0, 0) },
 | |
|             { "  2009    ApR", " %Y %b", DateTime(2009, 4, 0, 0, 0, 0, 0) },
 | |
|             { "200910", "%Y%m", DateTime(2009, 10, 0, 0, 0, 0, 0) },
 | |
|             { "  2009    10", " %Y %m", DateTime(2009, 10, 0, 0, 0, 0, 0) },
 | |
|             { "200910", "%Y%c", DateTime(2009, 10, 0, 0, 0, 0, 0) },
 | |
|             { "  2009    10", " %Y %c", DateTime(2009, 10, 0, 0, 0, 0, 0) },
 | |
|             { "01,5,2013", "%d,%m,%Y", DateTime(2013, 5, 1, 0, 0, 0, 0) },
 | |
|             { "01,5,2013", "%e,%m,%Y", DateTime(2013, 5, 1, 0, 0, 0, 0) },
 | |
|             { "7,5th,2012", "%m,%D,%Y", DateTime(2012, 7, 5, 0, 0, 0, 0) },
 | |
|             { "a09:30:17", "a%h:%i", DateTime(0, 0, 0, 9, 30, 0, 0) },
 | |
|             { "a09:30:17", "%h:%i", DateTime(0, 0, 0, 0, 0, 0, 0) },
 | |
|             { "9:30.170", "%h:%i.%f", DateTime(0, 0, 0, 9, 30, 0, 170000) },
 | |
|             { "178546 17", "%f  %H", DateTime(0, 0, 0, 17, 0, 0, 178546) },
 | |
|             { "2009march415", "%Y%b", DateTime(2009, 3, 0, 0, 0, 0, 0) },
 | |
|             { "  2009    July", " %Y %b", DateTime(2009, 7, 0, 0, 0, 0, 0) },
 | |
|             { "09  pm", "%h %p", DateTime(0, 0, 0, 21, 0, 0, 0) },
 | |
|             { "09:13:14pm", "%r", DateTime(0, 0, 0, 9, 13, 14, 0) },
 | |
|             { "12:13:14am", "%r", DateTime(0, 0, 0, 12, 13, 14, 0) },
 | |
|             { "92", "    %Y", DateTime(1992, 0, 0, 0, 0, 0, 0) },
 | |
|             { "9", "    %Y", DateTime(2009, 0, 0, 0, 0, 0, 0) },
 | |
|             { "2013 31", "%Y %j", DateTime(2013, 1, 31, 0, 0, 0, 0) },
 | |
|             { "2013 1 3", "%Y %U %w", DateTime(2013, 1, 9, 0, 0, 0, 0) },
 | |
|             { "2013 1 3", "%Y %u %w", DateTime(2013, 1, 9, 0, 0, 0, 0) },
 | |
|             { "2007 1 3", "%Y %U %w", DateTime(2007, 1, 10, 0, 0, 0, 0) },
 | |
|             { "2007 1 3", "%Y %u %w", DateTime(2007, 1, 3, 0, 0, 0, 0) },
 | |
|             { "2013 1 3", "%X %V %w", DateTime(2013, 1, 9, 0, 0, 0, 0) },
 | |
|             { "2013 1 3", "%X %v %w", DateTime(2013, 1, 9, 0, 0, 0, 0) },
 | |
|             { "2007 1 3", "%X %V %w", DateTime(2007, 1, 10, 0, 0, 0, 0) },
 | |
|             { "2007 1 3", "%X %v %w", DateTime(2007, 1, 3, 0, 0, 0, 0) },
 | |
|             { "33:30.170", "%h:%i.%f", DateTime(0, 0, 0, 0, 0, 0, 0) },
 | |
|             { "01,25,2013", "%d,%m,%Y", DateTime(0, 0, 0, 0, 0, 0, 0) },
 | |
|             { "%09:30:17", "%%%h:%i:%s", DateTime(0, 0, 0, 9, 30, 17, 0) },
 | |
|             { "2009 foobar", "%Y", DateTime(2009, 0, 0, 0, 0, 0, 0) },
 | |
|             { "2009-12-31", "%h:%i:%s %p", DateTime(0, 0, 0, 0, 0, 0, 0) },
 | |
|             { "12:00:01 AM", "%h:%i:%s %p", DateTime(0, 0, 0, 0, 0, 1, 0) },
 | |
|             { "12:00:01 PM", "%h:%i:%s %p", DateTime(0, 0, 0, 12, 0, 1, 0) },
 | |
|             { "11:00:01 PM", "%h:%i:%s %p", DateTime(0, 0, 0, 23, 0, 1, 0) },
 | |
|             { "11:00:01 AM", "%h:%i:%s %p", DateTime(0, 0, 0, 11, 0, 1, 0) },
 | |
|             { "10000-01-02", "%Y:%m:%d", DateTime(0, 0, 0, 0, 0, 0, 0) },
 | |
|         };
 | |
| 
 | |
|         for (unsigned i = 0; i < sizeof(date_tests) / sizeof(DateCheck); i++)
 | |
|         {
 | |
|             DateTime dt;
 | |
|             dt.year = 0;
 | |
|             dt.month = 0;
 | |
|             dt.day = 0;
 | |
|             dt.hour = 0;
 | |
|             dt.minute = 0;
 | |
|             dt.second = 0;
 | |
|             dt.msecond = 0;
 | |
| 
 | |
|             TimeExtractor extractor;
 | |
|             int ret = extractor.extractTime(date_tests[i].inputstr, date_tests[i].formatstr, dt);
 | |
| 
 | |
|             if ( ret != 0 )
 | |
|                 cout << "Extractor reported error for "
 | |
|                      << date_tests[i].inputstr << "," << date_tests[i].formatstr << endl;
 | |
| 
 | |
|             bool check = ((*(reinterpret_cast<uint64_t*> (&date_tests[i].date))) ==
 | |
|                           ((*(reinterpret_cast<uint64_t*> (&dt)))));
 | |
| 
 | |
|             if (!check)
 | |
|             {
 | |
|                 printf("For input \"%s\", format \"%s\", check 0x%016lx vs 0x%016lx\n",
 | |
|                        date_tests[i].inputstr,
 | |
|                        date_tests[i].formatstr,
 | |
|                        *(reinterpret_cast<uint64_t*> (&dt)),
 | |
|                        *(reinterpret_cast<uint64_t*>(&date_tests[i].date)) );
 | |
|                 show_datetime_debugs("check", dt);
 | |
|                 show_datetime_debugs("ref", date_tests[i].date);
 | |
|             }
 | |
| 
 | |
|             CPPUNIT_ASSERT( check );
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     void fe_getnumbertest()
 | |
|     {
 | |
|         const int MAX_VALS = 5;
 | |
|         struct Check
 | |
|         {
 | |
|             const char* str;
 | |
|             int         numvals;
 | |
|             int         vals[MAX_VALS];
 | |
|         };
 | |
| 
 | |
|         Check tests[] =
 | |
|         {
 | |
|             { " ", 0, {} },
 | |
|             { "0", 1, {0} },
 | |
|             { "0.0", 2, {0, 0} },
 | |
|             { "0:0.0", 3, {0, 0, 0} },
 | |
|             { "-0", 1, {0} },
 | |
|             { "0000-000", 1, {0} },
 | |
|             { "-2", 1, {-2} },
 | |
|             { "2223", 1, {2223} },
 | |
|             { "37", 1, {37} },
 | |
|             { "393", 1, {393} },
 | |
|             { "39-3", 1, {39} },
 | |
|             { "17-", 1, {17} },
 | |
|             { "10.2303", 2, {10, 2303} },
 | |
|             { "20:10.2303", 3, {20, 10, 2303} },
 | |
|             { "17:37", 2, {17, 37} },
 | |
|         };
 | |
| 
 | |
|         int a1[MAX_VALS] = { 0xdeadbeef };
 | |
| 
 | |
|         for (unsigned i = 0; i < sizeof(tests) / sizeof(Check); i++)
 | |
|         {
 | |
|             int rc1 = helpers::getNumbers(tests[i].str, a1, execplan::OP_ADD);
 | |
| 
 | |
|             cout << "For input \"" << tests[i].str << "\", numbers = " << rc1 << ",[";
 | |
| 
 | |
|             bool check = true;
 | |
| 
 | |
|             if (rc1 != tests[i].numvals)
 | |
|                 check = false;
 | |
| 
 | |
|             for (int j = 0; j < rc1; ++j)
 | |
|             {
 | |
|                 if (j > 0)
 | |
|                     cout << ',';
 | |
| 
 | |
|                 cout << a1[j];
 | |
| 
 | |
|                 if (a1[j] != tests[i].vals[j])
 | |
|                 {
 | |
|                     check = false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             cout << ']' << endl;
 | |
| 
 | |
|             CPPUNIT_ASSERT( check );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void fe_dateaddtest()
 | |
|     {
 | |
|         struct DateCheck
 | |
|         {
 | |
|             const char* intervalstr;
 | |
|             IntervalColumn::interval_type unit;
 | |
|             OpType      funcType;
 | |
|             DateTime    date;
 | |
|             DateTime    ref;
 | |
|         };
 | |
| 
 | |
|         DateCheck date_tests[] =
 | |
|         {
 | |
|             { "111111:22", IntervalColumn::INTERVAL_YEAR_MONTH, execplan::OP_ADD, DateTime(1997, 01, 01, 0, 0, 0, 0), DateTime(0, 0, 0, 0, 0, 0, 0) },
 | |
|             { "-30", IntervalColumn::INTERVAL_DAY, execplan::OP_ADD, DateTime(2013, 3, 1, 0, 0, 0, 0), DateTime(2013, 1, 30, 0, 0, 0, 0) },
 | |
|         };
 | |
| 
 | |
|         for (unsigned i = 0; i < sizeof(date_tests) / sizeof(DateCheck); i++)
 | |
|         {
 | |
|             DateTime dt;
 | |
| 
 | |
|             uint64_t timeval = *(reinterpret_cast<uint64_t*> (&date_tests[i].date));
 | |
|             uint64_t value = helpers::dateAdd( timeval, date_tests[i].intervalstr, date_tests[i].unit, false, date_tests[i].funcType );
 | |
| 
 | |
|             *(reinterpret_cast<uint64_t*> (&dt)) = value;
 | |
| 
 | |
|             bool check = ( value == *(reinterpret_cast<uint64_t*> (&date_tests[i].ref)));
 | |
| 
 | |
|             if (!check)
 | |
|             {
 | |
|                 printf("For interval \"%s\", check 0x%016lx vs 0x%016lx\n",
 | |
|                        date_tests[i].intervalstr,
 | |
|                        *(reinterpret_cast<uint64_t*> (&dt)),
 | |
|                        *(reinterpret_cast<uint64_t*>(&date_tests[i].ref)) );
 | |
|                 show_datetime_debugs("check", dt);
 | |
|                 show_datetime_debugs("ref", date_tests[i].ref);
 | |
|             }
 | |
| 
 | |
|             CPPUNIT_ASSERT( check );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void fe_daynametest()
 | |
|     {
 | |
|         struct DateCheck
 | |
|         {
 | |
|             DateTime    date;
 | |
|             const char* dayname;
 | |
|         };
 | |
| 
 | |
|         DateCheck date_tests[] =
 | |
|         {
 | |
|             { DateTime(1997, 01, 01, 0, 0, 0, 0), "Wednesday" },
 | |
|         };
 | |
| 
 | |
|         for (unsigned i = 0; i < sizeof(date_tests) / sizeof(DateCheck); i++)
 | |
|         {
 | |
|             boost::gregorian::date d(date_tests[i].date.year, date_tests[i].date.month, date_tests[i].date.day);
 | |
|             uint32_t dayofweek = helpers::calc_mysql_weekday(date_tests[i].date.year, date_tests[i].date.month, date_tests[i].date.day, false);
 | |
| 
 | |
|             bool check = ( strcmp( helpers::weekdayFullNames[dayofweek].c_str(), date_tests[i].dayname ) == 0 );
 | |
| 
 | |
|             if (!check)
 | |
|             {
 | |
|                 printf("For date %s, check %s vs %s\n",
 | |
|                        to_simple_string(d).c_str(),
 | |
|                        helpers::weekdayFullNames[dayofweek].c_str(),
 | |
|                        date_tests[i].dayname );
 | |
|             }
 | |
| 
 | |
|             CPPUNIT_ASSERT( check );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     DateTime getDateTime(int64_t val)
 | |
|     {
 | |
|         if (val < 0 || val > helpers::TIMESTAMP_MAX_VALUE)
 | |
|             return 0;
 | |
| 
 | |
|         DateTime dt;
 | |
| 
 | |
|         struct tm tmp_tm;
 | |
|         time_t tmp_t = (time_t)val;
 | |
|         localtime_r(&tmp_t, &tmp_tm);
 | |
| 
 | |
|         //to->neg=0;
 | |
|         dt.year = (int64_t) ((tmp_tm.tm_year + 1900) % 10000);
 | |
|         dt.month = (int64_t) tmp_tm.tm_mon + 1;
 | |
|         dt.day = (int64_t) tmp_tm.tm_mday;
 | |
|         dt.hour = (int64_t) tmp_tm.tm_hour;
 | |
|         dt.minute = (int64_t) tmp_tm.tm_min;
 | |
|         dt.second = (int64_t) tmp_tm.tm_sec;
 | |
|         dt.msecond = 0;
 | |
|         return dt;
 | |
|     }
 | |
| 
 | |
|     void fe_fromunixtimetest()
 | |
|     {
 | |
|         struct DateCheck
 | |
|         {
 | |
|             int64_t     ts;
 | |
|             const char* formatstr;
 | |
|             const char* refstr;
 | |
|         };
 | |
| 
 | |
|         DateCheck date_tests[] =
 | |
|         {
 | |
|             { -26, "%H:%i:%s", "NULL" },
 | |
|             { 26, "%H:%i:%s", "18:00:26" },
 | |
|             { 0, "%H:%i:%s", "18:00:00" },
 | |
|         };
 | |
| 
 | |
|         for (unsigned i = 0; i < sizeof(date_tests) / sizeof(DateCheck); i++)
 | |
|         {
 | |
|             bool check = false;
 | |
|             string ret;
 | |
|             DateTime dt = getDateTime(date_tests[i].ts);
 | |
| 
 | |
|             if (*reinterpret_cast<int64_t*>(&dt) == 0)
 | |
|             {
 | |
|                 check = ( strcmp( date_tests[i].refstr, "NULL" ) == 0 );
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 ret = helpers::IDB_date_format(dt, date_tests[i].formatstr);
 | |
|                 check = ( strcmp( date_tests[i].refstr, ret.c_str() ) == 0 );
 | |
|             }
 | |
| 
 | |
|             if (!check)
 | |
|             {
 | |
|                 printf("For timestamp %ld, check %s vs %s\n",
 | |
|                        date_tests[i].ts,
 | |
|                        ret.c_str(),
 | |
|                        date_tests[i].refstr );
 | |
|             }
 | |
| 
 | |
|             CPPUNIT_ASSERT( check );
 | |
|         }
 | |
|     }
 | |
| 
 | |
| };
 | |
| 
 | |
| CPPUNIT_TEST_SUITE_REGISTRATION( FuncExpTest );
 | |
| 
 | |
| #include <cppunit/extensions/TestFactoryRegistry.h>
 | |
| #include <cppunit/ui/text/TestRunner.h>
 | |
| 
 | |
| int main( int argc, char** argv)
 | |
| {
 | |
|     CppUnit::TextUi::TestRunner runner;
 | |
|     CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
 | |
|     runner.addTest( registry.makeTest() );
 | |
|     bool wasSuccessful = runner.run( "", false );
 | |
|     return (wasSuccessful ? 0 : 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 |