You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +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
 |