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 
			
		
		
		
	
		
			
				
	
	
		
			363 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			363 lines
		
	
	
		
			10 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 ®istry = CppUnit::TestFactoryRegistry::getRegistry();
 | |
|   runner.addTest( registry.makeTest() );
 | |
|   bool wasSuccessful = runner.run( "", false );
 | |
|   return (wasSuccessful ? 0 : 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 |