You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +03:00 
			
		
		
		
	* MSan added with fixes for libc++ * libc++ sepatare build * add libc++ to ci * libstdc++ in CI * libcpp and msan to external projects * std::sqrt * awful_hack(ci): install whole llvm instead of libc++ in terrible way for test containers * Adding ddeb packages for teststages and repos * libc++ more for test container * save some money on debug * colored coredumps * revert ci * chore(ci): collect asan ubsan and libc++ build with mtr and regression status ignored
		
			
				
	
	
		
			685 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			685 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (C) 2014 InfiniDB, Inc.
 | |
|    Copyright (C) 2019 MariaDB Corporation
 | |
| 
 | |
|    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 */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <string>
 | |
| 
 | |
| #ifndef __STDC_FORMAT_MACROS
 | |
| #define __STDC_FORMAT_MACROS
 | |
| #endif
 | |
| 
 | |
| #include <cinttypes>
 | |
| #include <boost/algorithm/string/case_conv.hpp>
 | |
| #include <boost/tokenizer.hpp>
 | |
| 
 | |
| #include "dataconvert.h"
 | |
| #include "operator.h"
 | |
| #include "intervalcolumn.h"
 | |
| #include "treenode.h"
 | |
| 
 | |
| #ifndef ULONGLONG_MAX
 | |
| #define ULONGLONG_MAX ulonglong_max
 | |
| #endif
 | |
| namespace funcexp::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) || (day == 0 && month == 0 && year == 0))
 | |
|     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,
 | |
|                                    bool& isNull)
 | |
| {
 | |
|   if (!dataconvert::isDateValid(day, month, year) || (day == 0 && month == 0 && year == 0))
 | |
|   {
 | |
|     isNull = true;
 | |
|     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 = nullptr)
 | |
| {
 | |
|   // 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;
 | |
| 
 | |
|   bool isNullDummy = false;
 | |
|   uint32_t weekday = calc_mysql_weekday(year, 1, 1, !monday_first, isNullDummy);
 | |
| 
 | |
|   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 = true;
 | |
| 
 | |
|     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, bool isDateTime = true)
 | |
| {
 | |
|   int64_t days;
 | |
|   bool neg;
 | |
|   int128_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;
 | |
| 
 | |
|   if (isDateTime)
 | |
|   {
 | |
|     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);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     year1 = 0;
 | |
|     month1 = 0;
 | |
|     day1 = (time1 >> 52) & 0x7ff;
 | |
|     hour1 = (time1 >> 40) & 0xfff;
 | |
|     min1 = (time1 >> 32) & 0xff;
 | |
|     sec1 = (time1 >> 24) & 0xff;
 | |
|     msec1 = time1 & 0xffffff;
 | |
| 
 | |
|     year2 = 0;
 | |
|     month2 = 0;
 | |
|     day2 = (time2 >> 52) & 0x7ff;
 | |
|     hour2 = (time2 >> 40) & 0xfff;
 | |
|     min2 = (time2 >> 32) & 0xff;
 | |
|     sec2 = (time2 >> 24) & 0xff;
 | |
|     msec2 = time2 & 0xffffff;
 | |
|   }
 | |
| 
 | |
|   days = calc_mysql_daynr(year1, month1, day1);
 | |
| 
 | |
|   days -= l_sign * calc_mysql_daynr(year2, month2, day2);
 | |
| 
 | |
|   microseconds = (int128_t(days) * (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 = false;
 | |
| 
 | |
|   if (microseconds < 0)
 | |
|   {
 | |
|     microseconds = -microseconds;
 | |
|     neg = true;
 | |
|   }
 | |
| 
 | |
|   *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;
 | |
| }
 | |
| 
 | |
| template <typename T>
 | |
| inline void decimalPlaceDec(int64_t& d, 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.empty())
 | |
|     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 (auto value : expr)
 | |
|   {
 | |
|     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.empty())
 | |
|     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 (char value : expr)
 | |
|   {
 | |
|     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
 | |
| {
 | |
|   boost::to_lower(day);
 | |
| 
 | |
|   if (day == "sunday" || day == "sun")
 | |
|   {
 | |
|     return 0;
 | |
|   }
 | |
|   else if (day == "monday" || day == "mon")
 | |
|   {
 | |
|     return 1;
 | |
|   }
 | |
|   else if (day == "tuesday" || day == "tue")
 | |
|   {
 | |
|     return 2;
 | |
|   }
 | |
|   else if (day == "wednesday" || day == "wed")
 | |
|   {
 | |
|     return 3;
 | |
|   }
 | |
|   else if (day == "thursday" || day == "thu")
 | |
|   {
 | |
|     return 4;
 | |
|   }
 | |
|   else if (day == "friday" || day == "fri")
 | |
|   {
 | |
|     return 5;
 | |
|   }
 | |
|   else if (day == "saturday" || day == "sat")
 | |
|   {
 | |
|     return 6;
 | |
|   }
 | |
| 
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| inline std::string intToString(int64_t i)
 | |
| {
 | |
|   char buf[32];
 | |
|   snprintf(buf, sizeof(buf), "%" PRId64 "", i);
 | |
|   return buf;
 | |
| }
 | |
| 
 | |
| inline std::string uintToString(uint64_t i)
 | |
| {
 | |
|   char buf[32];
 | |
|   snprintf(buf, sizeof(buf), "%" PRIu64 "", i);
 | |
|   return buf;
 | |
| }
 | |
| 
 | |
| inline std::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, sizeof(buf), "%f", d);
 | |
|   return buf;
 | |
| }
 | |
| 
 | |
| inline std::string longDoubleToString(long double ld)
 | |
| {
 | |
|   // long 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, sizeof(buf), "%Lf", ld);
 | |
|   return buf;
 | |
| }
 | |
| 
 | |
| 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&, bool& isNull);
 | |
| const std::string timediff(int64_t, int64_t, bool isDateTime = true);
 | |
| const char* convNumToStr(int64_t, char*, int);
 | |
| 
 | |
| }  // namespace funcexp::helpers
 |