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 
			
		
		
		
	The flags mask logic for the week function was incorrect. This patch fixes it so that the behaviour is the same as MariaDB's
		
			
				
	
	
		
			732 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			732 lines
		
	
	
		
			16 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: funchelpers.h 3921 2013-06-19 18:59:56Z bwilkinson $
 | |
| 
 | |
| /** @file */
 | |
| 
 | |
| #ifndef FUNCHELPERS_H__
 | |
| #define FUNCHELPERS_H__
 | |
| 
 | |
| #include <string>
 | |
| 
 | |
| #ifndef _MSC_VER
 | |
| #ifndef __STDC_FORMAT_MACROS
 | |
| #define __STDC_FORMAT_MACROS
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #include <inttypes.h>
 | |
| #include <boost/algorithm/string/case_conv.hpp>
 | |
| #include <boost/regex.hpp>
 | |
| #include <boost/tokenizer.hpp>
 | |
| 
 | |
| #include "dataconvert.h"
 | |
| #include "operator.h"
 | |
| #include "intervalcolumn.h"
 | |
| #include "treenode.h"
 | |
| 
 | |
| #define ULONGLONG_MAX ulonglong_max
 | |
| 
 | |
| namespace funcexp
 | |
| {
 | |
| namespace helpers
 | |
| {
 | |
| 
 | |
| // 10 ** i
 | |
| const int64_t powerOf10_c[] = {
 | |
| 	1ll,
 | |
| 	10ll,
 | |
| 	100ll,
 | |
| 	1000ll,
 | |
| 	10000ll,
 | |
| 	100000ll,
 | |
| 	1000000ll,
 | |
| 	10000000ll,
 | |
| 	100000000ll,
 | |
| 	1000000000ll,
 | |
| 	10000000000ll,
 | |
| 	100000000000ll,
 | |
| 	1000000000000ll,
 | |
| 	10000000000000ll,
 | |
| 	100000000000000ll,
 | |
| 	1000000000000000ll,
 | |
| 	10000000000000000ll,
 | |
| 	100000000000000000ll,
 | |
| 	1000000000000000000ll };
 | |
| 
 | |
| 
 | |
| // max integer number of i digits
 | |
| const int64_t maxNumber_c[] = {
 | |
| 	0ll,
 | |
| 	9ll,
 | |
| 	99ll,
 | |
| 	999ll,
 | |
| 	9999ll,
 | |
| 	99999ll,
 | |
| 	999999ll,
 | |
| 	9999999ll,
 | |
| 	99999999ll,
 | |
| 	999999999ll,
 | |
| 	9999999999ll,
 | |
| 	99999999999ll,
 | |
| 	999999999999ll,
 | |
| 	9999999999999ll,
 | |
| 	99999999999999ll,
 | |
| 	999999999999999ll,
 | |
| 	9999999999999999ll,
 | |
| 	99999999999999999ll,
 | |
| 	999999999999999999ll };
 | |
| 
 | |
| 
 | |
| const uint32_t TIMESTAMP_MAX_YEAR = 2038;
 | |
| const uint32_t TIMESTAMP_MIN_YEAR = (1970 - 1);
 | |
| const int TIMESTAMP_MIN_VALUE = 1;
 | |
| const int64_t TIMESTAMP_MAX_VALUE = 0x7FFFFFFFL;
 | |
| const unsigned long long MAX_NEGATIVE_NUMBER	= 0x8000000000000000ULL;
 | |
| const long long LONGLONG_MIN =  0x8000000000000000LL;
 | |
| const int INIT_CNT = 9;
 | |
| const unsigned long LFACTOR  = 1000000000;
 | |
| const unsigned long long LFACTOR1 = 10000000000ULL;
 | |
| const unsigned long long LFACTOR2 = 100000000000ULL;
 | |
| const unsigned long long ulonglong_max= ~(unsigned long long) 0;
 | |
| 
 | |
| static std::string monthFullNames[13] = 
 | |
| {
 | |
| 	"NON_VALID",
 | |
| 	"January",
 | |
| 	"February",
 | |
| 	"March",
 | |
| 	"April",
 | |
| 	"May",
 | |
| 	"June",
 | |
| 	"July",
 | |
| 	"August",
 | |
| 	"September",
 | |
| 	"October",
 | |
| 	"November",
 | |
| 	"December"	
 | |
| };
 | |
| 
 | |
| static std::string monthAbNames[13] = 
 | |
| {
 | |
| 	"NON_VALID",
 | |
| 	"Jan",
 | |
| 	"Feb",
 | |
| 	"Mar",
 | |
| 	"Apr",
 | |
| 	"May",
 | |
| 	"Jun",
 | |
| 	"Jul",
 | |
| 	"Aug",
 | |
| 	"Sep",
 | |
| 	"Oct",
 | |
| 	"Nov",
 | |
| 	"Dec"	
 | |
| };
 | |
| 
 | |
| static std::string weekdayFullNames[8] = 
 | |
| {
 | |
| 	"Monday",
 | |
| 	"Tuesday",
 | |
| 	"Wednesday",
 | |
| 	"Thursday",
 | |
| 	"Friday",
 | |
| 	"Saturday",
 | |
| 	"Sunday"
 | |
| };
 | |
| 
 | |
| static std::string weekdayAbNames[8] = 
 | |
| {
 | |
| 	"Mon",
 | |
| 	"Tue",
 | |
| 	"Wed",
 | |
| 	"Thu",
 | |
| 	"Fri",
 | |
| 	"Sat",
 | |
| 	"Sun"
 | |
| };
 | |
| 
 | |
| static std::string dayOfMonth[32] = 
 | |
| {"0th", "1st", "2nd", "3rd", "4th",
 | |
|  "5th", "6th", "7th", "8th", "9th",
 | |
|  "10th", "11th", "12th", "13th", "14th",
 | |
|  "15th", "16th", "17th", "18th", "19th", "20th", 
 | |
|  "21st", "22nd", "23rd", "24th", "25th",
 | |
|  "26th", "27th", "28th", "29th", "30th",
 | |
|  "31st"
 | |
|  };
 | |
| 
 | |
| static uint8_t days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
 | |
| 
 | |
| // Given a date, calculate the number of days since year 0
 | |
| // This is a mirror of calc_daynr, at a later date we should use my_time.h
 | |
| inline uint32_t calc_mysql_daynr( uint32_t year, uint32_t month, uint32_t day )
 | |
| {
 | |
|     int temp;
 | |
|     int y = year;
 | |
|     long delsum;
 | |
| 
 | |
| 	if( !dataconvert::isDateValid( day, month, year ) )
 | |
| 		return 0;
 | |
| 
 | |
|     delsum= (long) (365 * y + 31 *((int) month - 1) + (int) day);
 | |
|     if (month <= 2)
 | |
|         y--;
 | |
|     else
 | |
|         delsum-= (long) ((int) month * 4 + 23) / 10;
 | |
|     temp=(int) ((y/100+1)*3)/4;
 | |
| 
 | |
|     return delsum+(int) y/4-temp;
 | |
| }
 | |
| 
 | |
| // used by get_date_from_mysql_daynr() and calc_mysql_week()
 | |
| inline uint32_t calc_mysql_days_in_year(uint32_t year)
 | |
| {
 | |
|     return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
 | |
|             366 : 365);
 | |
| }
 | |
| 
 | |
| // convert from a MySQL day number (offset from year 0) to a date
 | |
| // This is a mirror of get_date_from_daynr, at a later date we should use sql_time.h
 | |
| inline void get_date_from_mysql_daynr(long daynr,dataconvert::DateTime & dateTime)
 | |
| {
 | |
|     uint32_t year, temp, leap_day, day_of_year, days_in_year;
 | |
|     uint8_t *month_pos;
 | |
|     uint32_t ret_year, ret_month, ret_day;
 | |
|     const int MAX_DAY_NUMBER= 3652424;
 | |
| 
 | |
| 
 | |
|     if (daynr < 366 || daynr > MAX_DAY_NUMBER)
 | |
|     {
 | |
|         dateTime.year= dateTime.month = dateTime.day =0;
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     year= (uint32_t) (daynr*100 / 36525L);
 | |
|     temp=(((year-1)/100+1)*3)/4;
 | |
|     day_of_year=(uint) (daynr - (long) year * 365L) - (year-1)/4 +temp;
 | |
|     while (day_of_year > (days_in_year= calc_mysql_days_in_year(year)))
 | |
|     {
 | |
|         day_of_year-=days_in_year;
 | |
|         (year)++;
 | |
|     }
 | |
|     leap_day=0;
 | |
|     if (days_in_year == 366)
 | |
|     {
 | |
|         if (day_of_year > 31+28)
 | |
|         {
 | |
|             day_of_year--;
 | |
|             if (day_of_year == 31+28)
 | |
|                 leap_day=1;		/* Handle leapyears leapday */
 | |
|         }
 | |
|     }
 | |
|     ret_month=1;
 | |
|     for (month_pos= days_in_month ;
 | |
|          day_of_year > (uint32_t) *month_pos ;
 | |
|          day_of_year-= *(month_pos++), (ret_month)++)
 | |
|       ;
 | |
|     ret_year=year;
 | |
|     ret_day=day_of_year+leap_day;
 | |
| 
 | |
|     dateTime.year = ret_year;
 | |
|     dateTime.month = ret_month;
 | |
|     dateTime.day = ret_day;
 | |
| }
 | |
| 
 | |
| // Returns the weekday index for a given date:
 | |
| //   if sundayFirst:
 | |
| //       0 = Sunday, 1 = Monday, ..., 6 = Saturday
 | |
| //   else:
 | |
| //       0 = Monday, 1 = Tuesday, ..., 6 = Sunday
 | |
| // This is a mirror of calc_weekday, at a later date we should use sql_time.h
 | |
| inline uint32_t calc_mysql_weekday( uint32_t year, uint32_t month, uint32_t day, bool sundayFirst )
 | |
| {
 | |
| 	if( !dataconvert::isDateValid( day, month, year ) )
 | |
| 		return 0;
 | |
| 
 | |
|     uint32_t daynr = calc_mysql_daynr(year, month, day);
 | |
|     return ((int) ((daynr + 5L + (sundayFirst ? 1L : 0L)) % 7));
 | |
| 
 | |
| }
 | |
| 
 | |
| // Flags for calc_mysql_week
 | |
| const uint32_t WEEK_MONDAY_FIRST  = 1;
 | |
| const uint32_t WEEK_NO_ZERO       = 2;
 | |
| const uint32_t WEEK_GT_THREE_DAYS = 4;
 | |
| 
 | |
| // Takes a MySQL WEEK() function mode setting and converts to a bitmask
 | |
| // used by calc_mysql_week() mirror of MariaDB's week_mode()
 | |
| inline int16_t convert_mysql_mode_to_modeflags( int16_t mode )
 | |
| {
 | |
| 	if(!(mode & WEEK_MONDAY_FIRST))
 | |
| 		mode ^= WEEK_GT_THREE_DAYS;
 | |
| 
 | |
| 	return mode;
 | |
| }
 | |
| 
 | |
| // Returns a week index conforming to the MySQL WEEK() function.  Note
 | |
| // that modeflags is not the MySQL mode - it is a bitmask of the abvoe
 | |
| // 3 flags.  The utility function convert_mysql_mode_to_modeflags should
 | |
| // be applied to the MySQL mode before calling this function (or the
 | |
| // flags may be used directly).  The optional argument is for callers
 | |
| // that need to know the year that the week actually corresponds to -
 | |
| // see MySQL documentation for how the year returned can be different
 | |
| // than the year of the input date
 | |
| //
 | |
| // This is a mirror of calc_week, at a later date we should use sql_time.h
 | |
| inline uint32_t calc_mysql_week( uint32_t year, uint32_t month, uint32_t day,
 | |
| 						   	     int16_t modeflags,
 | |
| 						   	     uint32_t* weekyear = 0 )
 | |
| {
 | |
|     // need to make sure that the date is valid
 | |
| 	if( !dataconvert::isDateValid( day, month, year ) )
 | |
| 		return 0;
 | |
| 
 | |
| 
 | |
|     uint32_t days;
 | |
|     uint32_t daynr=calc_mysql_daynr(year,month,day);
 | |
|     uint32_t first_daynr=calc_mysql_daynr(year,1,1);
 | |
|     bool monday_first= modeflags & WEEK_MONDAY_FIRST;
 | |
|     bool week_year= modeflags & WEEK_NO_ZERO;
 | |
|     bool first_weekday= modeflags & WEEK_GT_THREE_DAYS;
 | |
| 
 | |
|     uint32_t weekday=calc_mysql_weekday(year, 1, 1, !monday_first);
 | |
|     if (weekyear)
 | |
|     {
 | |
|         *weekyear=year;
 | |
|     }
 | |
| 
 | |
|     if (month == 1 && day <= 7-weekday)
 | |
|     {
 | |
|         if (!week_year && 
 | |
|     	((first_weekday && weekday != 0) ||
 | |
|     	 (!first_weekday && weekday >= 4)))
 | |
|             return 0;
 | |
|         week_year= 1;
 | |
|         if (weekyear)
 | |
|         {
 | |
|             (*weekyear)--;
 | |
|         }
 | |
|         year--;
 | |
|         first_daynr-= (days=calc_mysql_days_in_year(year));
 | |
|         weekday= (weekday + 53*7- days) % 7;
 | |
|     }
 | |
| 
 | |
|     if ((first_weekday && weekday != 0) ||
 | |
|       (!first_weekday && weekday >= 4))
 | |
|         days= daynr - (first_daynr+ (7-weekday));
 | |
|     else
 | |
|         days= daynr - (first_daynr - weekday);
 | |
| 
 | |
|     if (week_year && days >= 52*7)
 | |
|     {
 | |
|         weekday= (weekday + calc_mysql_days_in_year(year)) % 7;
 | |
|         if ((!first_weekday && weekday < 4) ||
 | |
|     	(first_weekday && weekday == 0))
 | |
|         {
 | |
|             if (weekyear)
 | |
|             {
 | |
|                 (*weekyear)++;
 | |
|             }
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
|     return days/7+1;
 | |
| }
 | |
| 
 | |
| inline bool calc_time_diff(int64_t time1, int64_t time2, int l_sign, long long *seconds_out, long long *microseconds_out)
 | |
| {
 | |
|   int64_t days;
 | |
|   bool neg;
 | |
|   int64_t microseconds;
 | |
| 
 | |
| 	uint64_t year1 = 0, 
 | |
| 	         month1 = 0, 
 | |
| 	         day1 = 0, 
 | |
| 	         hour1 = 0, 
 | |
| 	         min1 = 0, 
 | |
| 	         sec1 = 0, 
 | |
| 	         msec1 = 0;
 | |
| 
 | |
| 	uint64_t year2 = 0, 
 | |
| 	         month2 = 0, 
 | |
| 	         day2 = 0, 
 | |
| 	         hour2 = 0, 
 | |
| 	         min2 = 0, 
 | |
| 	         sec2 = 0, 
 | |
| 	         msec2 = 0;
 | |
| 	
 | |
| 	year1 = (uint32_t)((time1 >> 48) & 0xffff);
 | |
| 	month1 = (uint32_t)((time1 >> 44) & 0xf);
 | |
| 	day1 = (uint32_t)((time1 >> 38) & 0x3f);
 | |
| 	hour1 = (uint32_t)((time1 >> 32) & 0x3f);
 | |
| 	min1 = (uint32_t)((time1 >> 26) & 0x3f);
 | |
| 	sec1 = (uint32_t)((time1 >> 20) & 0x3f);
 | |
| 	msec1 = (uint32_t)((time1 & 0xfffff));
 | |
| 
 | |
| 	year2 = (uint32_t)((time2 >> 48) & 0xffff);
 | |
| 	month2 = (uint32_t)((time2 >> 44) & 0xf);
 | |
| 	day2 = (uint32_t)((time2 >> 38) & 0x3f);
 | |
| 	hour2 = (uint32_t)((time2 >> 32) & 0x3f);
 | |
| 	min2 = (uint32_t)((time2 >> 26) & 0x3f);
 | |
| 	sec2 = (uint32_t)((time2 >> 20) & 0x3f);
 | |
| 	msec2 = (uint32_t)((time2 & 0xfffff));
 | |
| 
 | |
|     days= calc_mysql_daynr(year1, month1, day1);
 | |
| 
 | |
|     days-= l_sign*calc_mysql_daynr(year2, month2, day2);
 | |
| 
 | |
|   	microseconds= ((long long)days*(long)(86400) +
 | |
|                  (long long)(hour1*3600L +
 | |
|                             min1*60L +
 | |
|                             sec1) -
 | |
|                  l_sign*(long long)(hour2*3600L +
 | |
|                                    min2*60L +
 | |
|                                    sec2)) * (long long)(1000000) +
 | |
|                 (long long)msec1 -
 | |
|                 l_sign*(long long)msec2;
 | |
| 
 | |
|   neg= 0;
 | |
|   if (microseconds < 0)
 | |
|   {
 | |
|     microseconds= -microseconds;
 | |
|     neg= 1;
 | |
|   }
 | |
|   *seconds_out= microseconds/1000000L;
 | |
|   *microseconds_out= (long long) (microseconds%1000000L);
 | |
|   return neg;
 | |
| }
 | |
| 
 | |
| inline int power ( int16_t a ) {
 | |
| 	int b = 1;
 | |
| 	for ( int i=0 ; i < a ; i++ )
 | |
| 	{
 | |
| 		b = b * 10;
 | |
| 	}
 | |
| 	return b;
 | |
| }
 | |
| 
 | |
| inline void decimalPlaceDec(int64_t& d, int64_t& p, int8_t& s)
 | |
| {
 | |
| 	// find new scale if D < s
 | |
| 	if (d < s)
 | |
| 	{
 | |
| 		int64_t t = s;
 | |
| 		s = d;  // the new scale
 | |
| 		d -= t;
 | |
| 		int64_t i = (d >= 0) ? d : (-d);
 | |
| 		while (i--)
 | |
| 			p *= 10;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		d = s;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| inline uint32_t convertMonth (std::string month)
 | |
| {
 | |
| 	uint32_t value = 0;
 | |
| 	
 | |
| 	boost::algorithm::to_lower(month);
 | |
| 
 | |
| 		if ( month == "jan" || month == "january" )
 | |
| 		{
 | |
| 			value = 1;
 | |
| 		}
 | |
| 		else if ( month == "feb" || month == "february" )
 | |
| 		{
 | |
| 			value = 2;
 | |
| 		}
 | |
| 		else if ( month == "mar" || month == "march" )
 | |
| 		{
 | |
| 			value = 3;
 | |
| 		}
 | |
| 		else if ( month == "apr" || month == "april" )
 | |
| 		{
 | |
| 			value = 4;
 | |
| 		}
 | |
| 		else if ( month == "may" )
 | |
| 		{
 | |
| 			value = 5;
 | |
| 		}
 | |
| 		else if ( month == "jun" || month == "june" )
 | |
| 		{
 | |
| 			value = 6;
 | |
| 		}
 | |
| 		else if ( month == "jul" || month == "july" )
 | |
| 		{
 | |
| 			value = 7;
 | |
| 		}
 | |
| 		else if ( month == "aug" || month == "august" )
 | |
| 		{
 | |
| 			value = 8;
 | |
| 		}
 | |
| 		else if ( month == "sep" || month == "september" )
 | |
| 		{
 | |
| 			value = 9;
 | |
| 		}
 | |
| 		else if ( month == "oct" || month == "october" )
 | |
| 		{
 | |
| 			value = 10;
 | |
| 		}
 | |
| 		else if ( month == "nov" || month == "november" )
 | |
| 		{
 | |
| 			value = 11;
 | |
| 		}
 | |
| 		else if ( month == "dec" || month == "december" )
 | |
| 		{
 | |
| 			value = 12;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			value = 0;
 | |
| 		}
 | |
| 	return value;
 | |
| }
 | |
| 
 | |
| class to_lower
 | |
| {
 | |
|     public:
 | |
|         char operator() (char c) const            // notice the return type
 | |
|         {
 | |
|             return tolower(c);
 | |
|         }
 | |
| };
 | |
| 
 | |
| 
 | |
| inline int  getNumbers( const std::string& expr, int64_t *array, execplan::OpType funcType)
 | |
| {
 | |
| 	int index = 0;
 | |
| 
 | |
| 	int funcNeg = 1;
 | |
| 	if ( funcType == execplan::OP_SUB )
 | |
| 		funcNeg = -1;
 | |
| 
 | |
| 	if ( expr.size() == 0 )
 | |
| 		return 0;
 | |
| 
 | |
| 	// @bug 4703 reworked this code to avoid use of incrementally
 | |
| 	//           built string to hold temporary values while
 | |
| 	//           scanning expr for numbers.  This function is now
 | |
| 	//           covered by a unit test in tdriver.cpp
 | |
| 	bool foundNumber = false;
 | |
| 	int64_t  number = 0;
 | |
| 	int  neg = 1;
 | |
| 	for ( unsigned int i=0 ; i < expr.size() ; i++ )
 | |
| 	{
 | |
| 		char value = expr[i];
 | |
| 		if ( (value >= '0' && value <= '9') )
 | |
| 		{
 | |
| 			foundNumber = true;
 | |
| 			number = ( number * 10 ) + ( value - '0' );
 | |
| 		}
 | |
| 		else if ( value == '-' && !foundNumber )
 | |
| 		{
 | |
| 			neg = -1;
 | |
| 		}
 | |
| 		else if ( value == '-')
 | |
| 		{
 | |
| 			// this is actually an error condition - it means that
 | |
| 			// input came in with something like NN-NN (i.e. a dash
 | |
| 			// between two numbers.  To match prior code we will
 | |
| 			// return the number up to the dash and just return
 | |
| 			array[index] = number * funcNeg * neg;
 | |
| 			index++;
 | |
| 
 | |
| 			return index;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if ( foundNumber )
 | |
| 			{
 | |
| 				array[index] = number * funcNeg * neg;
 | |
| 				number = 0;
 | |
| 				neg = 1;
 | |
| 				index++;
 | |
| 
 | |
| 				if ( index > 9 )
 | |
| 					return index;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if ( foundNumber )
 | |
| 	{
 | |
| 		array[index] = number * funcNeg * neg;
 | |
| 		index++;
 | |
| 	}
 | |
| 
 | |
| 	return index;
 | |
| }
 | |
| 
 | |
| 
 | |
| inline int  getNumbers( const std::string& expr, int *array, execplan::OpType funcType)
 | |
| {
 | |
| 	int index = 0;
 | |
| 
 | |
| 	int funcNeg = 1;
 | |
| 	if ( funcType == execplan::OP_SUB )
 | |
| 		funcNeg = -1;
 | |
| 
 | |
| 	if ( expr.size() == 0 )
 | |
| 		return 0;
 | |
| 
 | |
| 	// @bug 4703 reworked this code to avoid use of incrementally
 | |
| 	//           built string to hold temporary values while
 | |
| 	//           scanning expr for numbers.  This function is now
 | |
| 	//           covered by a unit test in tdriver.cpp
 | |
| 	bool foundNumber = false;
 | |
| 	int  number = 0;
 | |
| 	int  neg = 1;
 | |
| 	for ( unsigned int i=0 ; i < expr.size() ; i++ )
 | |
| 	{
 | |
| 		char value = expr[i];
 | |
| 		if ( (value >= '0' && value <= '9') )
 | |
| 		{
 | |
| 			foundNumber = true;
 | |
| 			number = ( number * 10 ) + ( value - '0' );
 | |
| 		}
 | |
| 		else if ( value == '-' && !foundNumber )
 | |
| 		{
 | |
| 			neg = -1;
 | |
| 		}
 | |
| 		else if ( value == '-')
 | |
| 		{
 | |
| 			// this is actually an error condition - it means that
 | |
| 			// input came in with something like NN-NN (i.e. a dash
 | |
| 			// between two numbers.  To match prior code we will
 | |
| 			// return the number up to the dash and just return
 | |
| 			array[index] = number * funcNeg * neg;
 | |
| 			index++;
 | |
| 
 | |
| 			return index;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if ( foundNumber )
 | |
| 			{
 | |
| 				array[index] = number * funcNeg * neg;
 | |
| 				number = 0;
 | |
| 				neg = 1;
 | |
| 				index++;
 | |
| 
 | |
| 				if ( index > 9 )
 | |
| 					return index;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if ( foundNumber )
 | |
| 	{
 | |
| 		array[index] = number * funcNeg * neg;
 | |
| 		index++;
 | |
| 	}
 | |
| 
 | |
| 	return index;
 | |
| }
 | |
| 
 | |
| inline int dayOfWeek(std::string day) //Sunday = 0
 | |
| {
 | |
| 	int value = -1;
 | |
| 	boost::to_lower(day);
 | |
| 
 | |
| 	if ( day == "sunday" || day == "sun" )
 | |
| 	{
 | |
| 		value = 0;
 | |
| 	}
 | |
| 	else if ( day == "monday" || day == "mon" )
 | |
| 	{
 | |
| 		value = 1;
 | |
| 	}
 | |
| 	else if ( day == "tuesday" || day == "tue" )
 | |
| 	{
 | |
| 		value = 2;
 | |
| 	}
 | |
| 	else if ( day == "wednesday" || day == "wed" )
 | |
| 	{
 | |
| 		value = 3;
 | |
| 	}
 | |
| 	else if ( day == "thursday" || day == "thu" )
 | |
| 	{
 | |
| 		value = 4;
 | |
| 	}
 | |
| 	else if ( day == "friday" || day == "fri" )
 | |
| 	{
 | |
| 		value = 5;
 | |
| 	}
 | |
| 	else if ( day == "saturday" || day == "sat" )
 | |
| 	{
 | |
| 		value = 6;
 | |
| 	}	
 | |
| 	else
 | |
| 	{
 | |
| 		value = -1;
 | |
| 	}
 | |
| 	return value;
 | |
| 
 | |
| }
 | |
| 
 | |
| inline
 | |
| string intToString(int64_t i)
 | |
| {
 | |
|     char buf[32];
 | |
| #ifndef _MSC_VER
 | |
|     snprintf(buf, 32, "%" PRId64 "", i);
 | |
| #else
 | |
|     snprintf(buf, 32, "%lld", i);
 | |
| #endif
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| inline
 | |
| string uintToString(uint64_t i)
 | |
| {
 | |
|     char buf[32];
 | |
| #ifndef _MSC_VER
 | |
|     snprintf(buf, 32, "%" PRIu64 "", i);
 | |
| #else
 | |
|     snprintf(buf, 32, "%llu", i);
 | |
| #endif
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| inline
 | |
| string doubleToString(double d)
 | |
| {
 | |
|     // double's can be *really* long to print out.  Max mysql
 | |
|     // is e308 so allow for 308 + 36 decimal places minimum.
 | |
|     char buf[384];
 | |
|     snprintf(buf, 384, "%f", d);
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| //@bug6146, remove duplicate function with incorrect impl. Use the DataConvert::decimalToString()
 | |
| //string decimalToString( execplan::IDB_Decimal x, int p )
 | |
| 
 | |
| 
 | |
| uint64_t dateAdd( uint64_t time, const std::string& expr, execplan::IntervalColumn::interval_type unit, bool dateType, execplan::OpType funcType );
 | |
| const std::string IDB_date_format(const dataconvert::DateTime&, const std::string&);
 | |
| const std::string timediff(int64_t, int64_t);
 | |
| const char *convNumToStr(int64_t, char*, int);
 | |
| 
 | |
| } //namespace funcexp::helpers
 | |
| } //namespace funcexp
 | |
| 
 | |
| #endif
 |