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 
			
		
		
		
	* Fixes of bugs from ASAN warnings, part one * MQC as static library, with nifty counter for global map and mutex * Switch clang to 16 * link messageqcpp to execplan
		
			
				
	
	
		
			842 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			842 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: func_date_add.cpp 3905 2013-06-18 12:27:32Z bwilkinson $
 | 
						|
 *
 | 
						|
 *
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
#include <cstdlib>
 | 
						|
#include <string>
 | 
						|
using namespace std;
 | 
						|
 | 
						|
#include "boost/assign.hpp"
 | 
						|
using namespace boost::assign;
 | 
						|
 | 
						|
#include "functor_dtm.h"
 | 
						|
#include "functioncolumn.h"
 | 
						|
#include "intervalcolumn.h"
 | 
						|
#include "constantcolumn.h"
 | 
						|
#include "rowgroup.h"
 | 
						|
using namespace execplan;
 | 
						|
 | 
						|
#include "dataconvert.h"
 | 
						|
using namespace dataconvert;
 | 
						|
 | 
						|
#include "funchelpers.h"
 | 
						|
 | 
						|
namespace funcexp
 | 
						|
{
 | 
						|
namespace helpers
 | 
						|
{
 | 
						|
uint64_t dateAdd(uint64_t time, const string& expr, IntervalColumn::interval_type unit, bool dateType,
 | 
						|
                 OpType funcType)
 | 
						|
{
 | 
						|
  int array[10];
 | 
						|
  int64_t array2[10];
 | 
						|
 | 
						|
  int month_length[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 | 
						|
 | 
						|
  int32_t year = 0, month = 0, day = 0, hour = 0, monthSave = 0;
 | 
						|
 | 
						|
  int64_t min = 0, sec = 0, msec = 0;
 | 
						|
 | 
						|
  int32_t yearAdd = 0, monthAdd = 0, dayAdd = 0, hourAdd = 0;
 | 
						|
 | 
						|
  int64_t minAdd = 0, secAdd = 0, msecAdd = 0;
 | 
						|
 | 
						|
  if (dateType)
 | 
						|
  {
 | 
						|
    year = (uint32_t)((time >> 16) & 0xffff);
 | 
						|
    month = (uint32_t)((time >> 12) & 0xf);
 | 
						|
    day = (uint32_t)((time >> 6) & 0x3f);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    year = (uint32_t)((time >> 48) & 0xffff);
 | 
						|
    month = (uint32_t)((time >> 44) & 0xf);
 | 
						|
    day = (uint32_t)((time >> 38) & 0x3f);
 | 
						|
    hour = (uint32_t)((time >> 32) & 0x3f);
 | 
						|
    min = (uint32_t)((time >> 26) & 0x3f);
 | 
						|
    sec = (uint32_t)((time >> 20) & 0x3f);
 | 
						|
    msec = (uint32_t)((time & 0xfffff));
 | 
						|
  }
 | 
						|
 | 
						|
  monthSave = month;
 | 
						|
 | 
						|
  int index = -1;
 | 
						|
 | 
						|
  switch (unit)
 | 
						|
  {
 | 
						|
    case IntervalColumn::INTERVAL_MINUTE:
 | 
						|
    case IntervalColumn::INTERVAL_SECOND:
 | 
						|
    case IntervalColumn::INTERVAL_MICROSECOND: index = getNumbers(expr, array2, funcType); break;
 | 
						|
 | 
						|
    default: index = getNumbers(expr, array, funcType); break;
 | 
						|
  };
 | 
						|
 | 
						|
  if (index <= 0)
 | 
						|
    throw runtime_error("expression type is not supported");
 | 
						|
 | 
						|
  switch (unit)
 | 
						|
  {
 | 
						|
    case IntervalColumn::INTERVAL_YEAR:
 | 
						|
    {
 | 
						|
      yearAdd = array[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_QUARTER:
 | 
						|
    {
 | 
						|
      monthAdd = array[0] * 3;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_MONTH:
 | 
						|
    {
 | 
						|
      monthAdd = array[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_WEEK:
 | 
						|
    {
 | 
						|
      dayAdd = array[0] * 7;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_DAY:
 | 
						|
    {
 | 
						|
      dayAdd = array[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_HOUR:
 | 
						|
    {
 | 
						|
      hourAdd = array[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_MINUTE:
 | 
						|
    {
 | 
						|
      minAdd = array2[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_SECOND:
 | 
						|
    {
 | 
						|
      secAdd = array2[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_MICROSECOND:
 | 
						|
    {
 | 
						|
      msecAdd = array2[0];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_YEAR_MONTH:
 | 
						|
    {
 | 
						|
      if (index > 2)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        monthAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        yearAdd = array[0];
 | 
						|
        monthAdd = array[1];
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_DAY_HOUR:
 | 
						|
    {
 | 
						|
      if (index > 2)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        hourAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        dayAdd = array[0];
 | 
						|
        hourAdd = array[1];
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_DAY_MINUTE:
 | 
						|
    {
 | 
						|
      if (index > 3)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        minAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (index == 2)
 | 
						|
        {
 | 
						|
          hourAdd = array[0];
 | 
						|
          minAdd = array[1];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          dayAdd = array[0];
 | 
						|
          hourAdd = array[1];
 | 
						|
          minAdd = array[2];
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_DAY_SECOND:
 | 
						|
    {
 | 
						|
      if (index > 4)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        secAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (index == 2)
 | 
						|
        {
 | 
						|
          minAdd = array[0];
 | 
						|
          secAdd = array[1];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (index == 3)
 | 
						|
          {
 | 
						|
            hourAdd = array[0];
 | 
						|
            minAdd = array[1];
 | 
						|
            secAdd = array[2];
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            dayAdd = array[0];
 | 
						|
            hourAdd = array[1];
 | 
						|
            minAdd = array[2];
 | 
						|
            secAdd = array[3];
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_HOUR_MINUTE:
 | 
						|
    {
 | 
						|
      if (index > 2)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        minAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        hourAdd = array[0];
 | 
						|
        minAdd = array[1];
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_HOUR_SECOND:
 | 
						|
    {
 | 
						|
      if (index > 3)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        secAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (index == 2)
 | 
						|
        {
 | 
						|
          minAdd = array[0];
 | 
						|
          secAdd = array[1];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          hourAdd = array[0];
 | 
						|
          minAdd = array[1];
 | 
						|
          secAdd = array[2];
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_MINUTE_SECOND:
 | 
						|
    {
 | 
						|
      if (index > 2)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        secAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        minAdd = array[0];
 | 
						|
        secAdd = array[1];
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_DAY_MICROSECOND:
 | 
						|
    {
 | 
						|
      if (index > 5)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        msecAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (index == 2)
 | 
						|
        {
 | 
						|
          secAdd = array[0];
 | 
						|
          msecAdd = array[1];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (index == 3)
 | 
						|
          {
 | 
						|
            minAdd = array[0];
 | 
						|
            secAdd = array[1];
 | 
						|
            msecAdd = array[2];
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            if (index == 4)
 | 
						|
            {
 | 
						|
              hourAdd = array[0];
 | 
						|
              minAdd = array[1];
 | 
						|
              secAdd = array[2];
 | 
						|
              msecAdd = array[3];
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
              dayAdd = array[0];
 | 
						|
              hourAdd = array[1];
 | 
						|
              minAdd = array[2];
 | 
						|
              secAdd = array[3];
 | 
						|
              msecAdd = array[4];
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_HOUR_MICROSECOND:
 | 
						|
    {
 | 
						|
      if (index > 4)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        msecAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (index == 2)
 | 
						|
        {
 | 
						|
          secAdd = array[0];
 | 
						|
          msecAdd = array[1];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (index == 3)
 | 
						|
          {
 | 
						|
            minAdd = array[0];
 | 
						|
            secAdd = array[1];
 | 
						|
            msecAdd = array[2];
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            hourAdd = array[0];
 | 
						|
            minAdd = array[1];
 | 
						|
            secAdd = array[2];
 | 
						|
            msecAdd = array[3];
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_MINUTE_MICROSECOND:
 | 
						|
    {
 | 
						|
      if (index > 3)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        msecAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (index == 2)
 | 
						|
        {
 | 
						|
          secAdd = array[0];
 | 
						|
          msecAdd = array[1];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          minAdd = array[0];
 | 
						|
          secAdd = array[1];
 | 
						|
          msecAdd = array[2];
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IntervalColumn::INTERVAL_SECOND_MICROSECOND:
 | 
						|
    {
 | 
						|
      if (index > 2)
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if (index == 1)
 | 
						|
        msecAdd = array[0];
 | 
						|
      else
 | 
						|
      {
 | 
						|
        secAdd = array[0];
 | 
						|
        msecAdd = array[1];
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    default:
 | 
						|
      // should be impossible to get here since we checked the presence
 | 
						|
      // in the map, but just to be safe...
 | 
						|
      throw runtime_error("unit type is not supported");
 | 
						|
  };
 | 
						|
 | 
						|
  // calulate new date
 | 
						|
 | 
						|
  year += yearAdd;
 | 
						|
 | 
						|
  month += monthAdd;
 | 
						|
 | 
						|
  day += dayAdd;
 | 
						|
 | 
						|
  hour += hourAdd;
 | 
						|
 | 
						|
  min += minAdd;
 | 
						|
 | 
						|
  sec += secAdd;
 | 
						|
 | 
						|
  msec += msecAdd;
 | 
						|
 | 
						|
  if (msec > 999999)
 | 
						|
  {
 | 
						|
    int64_t secs = msec / 1000000;
 | 
						|
    sec += secs;
 | 
						|
    msec = msec - (secs * 1000000);
 | 
						|
  }
 | 
						|
 | 
						|
  if (msec < 0)
 | 
						|
  {
 | 
						|
    int64_t secs = 1 + (-msec / 1000000);
 | 
						|
    sec -= secs;
 | 
						|
    msec = msec + (secs * 1000000);
 | 
						|
  }
 | 
						|
 | 
						|
  if (sec > 59)
 | 
						|
  {
 | 
						|
    int64_t mins = sec / 60;
 | 
						|
    min += mins;
 | 
						|
    sec = sec - (mins * 60);
 | 
						|
  }
 | 
						|
 | 
						|
  if (sec < 0)
 | 
						|
  {
 | 
						|
    int64_t mins = 0;
 | 
						|
 | 
						|
    if ((sec + (-sec / 60) * 60) == 0 && sec != 0)
 | 
						|
      mins = (-sec / 60);
 | 
						|
    else
 | 
						|
      mins = 1 + (-sec / 60);
 | 
						|
 | 
						|
    min -= mins;
 | 
						|
    sec = sec + (mins * 60);
 | 
						|
 | 
						|
    if (sec >= 60)
 | 
						|
      sec = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (min > 59)
 | 
						|
  {
 | 
						|
    int hours = min / 60;
 | 
						|
    hour += hours;
 | 
						|
    min = min - (hours * 60);
 | 
						|
  }
 | 
						|
 | 
						|
  if (min < 0)
 | 
						|
  {
 | 
						|
    int hours = 0;
 | 
						|
 | 
						|
    if ((min + (-min / 60) * 60) == 0 && min != 0)
 | 
						|
      hours = (-min / 60);
 | 
						|
    else
 | 
						|
      hours = 1 + (-min / 60);
 | 
						|
 | 
						|
    hour -= hours;
 | 
						|
    min = min + (hours * 60);
 | 
						|
 | 
						|
    if (min >= 60)
 | 
						|
      min = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (hour > 23)
 | 
						|
  {
 | 
						|
    int days = hour / 24;
 | 
						|
    day += days;
 | 
						|
    hour = hour - (days * 24);
 | 
						|
  }
 | 
						|
 | 
						|
  if (hour < 0)
 | 
						|
  {
 | 
						|
    int days = 0;
 | 
						|
 | 
						|
    if ((hour + (-hour / 24) * 24) == 0 && hour != 0)
 | 
						|
      days = (-hour / 24);
 | 
						|
    else
 | 
						|
      days = 1 + (-hour / 24);
 | 
						|
 | 
						|
    day -= days;
 | 
						|
    hour = hour + (days * 24);
 | 
						|
 | 
						|
    if (hour >= 24)
 | 
						|
      hour = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  int tmpYear = year;
 | 
						|
 | 
						|
  if (isLeapYear(tmpYear))
 | 
						|
    month_length[2] = 29;
 | 
						|
  else
 | 
						|
    month_length[2] = 28;
 | 
						|
 | 
						|
  if (day > 0)
 | 
						|
  {
 | 
						|
    while (true)
 | 
						|
    {
 | 
						|
      int years = (monthSave - 1) / 12;
 | 
						|
 | 
						|
      //			tmpYear += years;
 | 
						|
      if (isLeapYear(tmpYear))
 | 
						|
        month_length[2] = 29;
 | 
						|
      else
 | 
						|
        month_length[2] = 28;
 | 
						|
 | 
						|
      int tmpMonth = monthSave - (years * 12);
 | 
						|
 | 
						|
      if (day <= month_length[tmpMonth])
 | 
						|
        break;
 | 
						|
 | 
						|
      month++;
 | 
						|
      day = day - month_length[tmpMonth];
 | 
						|
      monthSave++;
 | 
						|
 | 
						|
      if (monthSave > 12)
 | 
						|
      {
 | 
						|
        monthSave = 1;
 | 
						|
        tmpYear++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    while (true)
 | 
						|
    {
 | 
						|
      if (day > 0)
 | 
						|
        break;
 | 
						|
 | 
						|
      if (-day < month_length[monthSave])
 | 
						|
      {
 | 
						|
        if (monthSave == 0)
 | 
						|
        {
 | 
						|
          monthSave = 12;
 | 
						|
          tmpYear--;
 | 
						|
        }
 | 
						|
 | 
						|
        month--;
 | 
						|
        monthSave--;
 | 
						|
 | 
						|
        if (monthSave == 0)
 | 
						|
        {
 | 
						|
          monthSave = 12;
 | 
						|
          tmpYear--;
 | 
						|
        }
 | 
						|
 | 
						|
        if (monthSave == 2)
 | 
						|
        {
 | 
						|
          //		if ( dataconvert::DataConvert::isLeapYear(year) )
 | 
						|
          if (isLeapYear(tmpYear))
 | 
						|
            month_length[2] = 29;
 | 
						|
        }
 | 
						|
 | 
						|
        if (day < 1)
 | 
						|
          day = month_length[monthSave] + day;
 | 
						|
 | 
						|
        // BUG 5448 - changed from '==' to '<='
 | 
						|
        if (day <= 0)
 | 
						|
        {
 | 
						|
          if (monthSave == 0)
 | 
						|
          {
 | 
						|
            monthSave = 12;
 | 
						|
            tmpYear--;
 | 
						|
          }
 | 
						|
 | 
						|
          month--;
 | 
						|
          monthSave--;
 | 
						|
 | 
						|
          if (monthSave == 0)
 | 
						|
          {
 | 
						|
            monthSave = 12;
 | 
						|
            tmpYear--;
 | 
						|
          }
 | 
						|
 | 
						|
          if (monthSave == 2)
 | 
						|
          {
 | 
						|
            //		if ( dataconvert::DataConvert::isLeapYear(year) )
 | 
						|
            if (isLeapYear(tmpYear))
 | 
						|
              month_length[2] = 29;
 | 
						|
          }
 | 
						|
 | 
						|
          day = day + month_length[monthSave];
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (monthSave == 0)
 | 
						|
      {
 | 
						|
        monthSave = 12;
 | 
						|
        tmpYear--;
 | 
						|
 | 
						|
        if (isLeapYear(tmpYear))
 | 
						|
          month_length[2] = 29;
 | 
						|
        else
 | 
						|
          month_length[2] = 28;
 | 
						|
      }
 | 
						|
 | 
						|
      month--;
 | 
						|
      monthSave--;
 | 
						|
 | 
						|
      if (monthSave == 0)
 | 
						|
      {
 | 
						|
        monthSave = 12;
 | 
						|
        tmpYear--;
 | 
						|
 | 
						|
        if (isLeapYear(tmpYear))
 | 
						|
          month_length[2] = 29;
 | 
						|
        else
 | 
						|
          month_length[2] = 28;
 | 
						|
      }
 | 
						|
 | 
						|
      day = day + month_length[monthSave];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (month > 12)
 | 
						|
  {
 | 
						|
    int years = (month - 1) / 12;
 | 
						|
    year += years;
 | 
						|
    month = month - (years * 12);
 | 
						|
  }
 | 
						|
 | 
						|
  if (month < 1)
 | 
						|
  {
 | 
						|
    int years = 1 + ((-month) / 12);
 | 
						|
    year -= years;
 | 
						|
    month = month + (years * 12);
 | 
						|
  }
 | 
						|
 | 
						|
  if (isLeapYear(year))
 | 
						|
    month_length[2] = 29;
 | 
						|
  else
 | 
						|
    month_length[2] = 28;
 | 
						|
 | 
						|
  if (day > month_length[month])
 | 
						|
    day = month_length[month];
 | 
						|
 | 
						|
  if (year < 1000 || year > 9999)
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  uint64_t value;
 | 
						|
  dataconvert::DateTime aDatetime;
 | 
						|
  aDatetime.year = year;
 | 
						|
  aDatetime.month = month;
 | 
						|
  aDatetime.day = day;
 | 
						|
  aDatetime.hour = hour;
 | 
						|
  aDatetime.minute = min;
 | 
						|
  aDatetime.second = sec;
 | 
						|
  aDatetime.msecond = msec;
 | 
						|
  value = *(reinterpret_cast<uint64_t*>(&aDatetime));
 | 
						|
 | 
						|
  return value;
 | 
						|
}
 | 
						|
}  // namespace helpers
 | 
						|
 | 
						|
CalpontSystemCatalog::ColType Func_date_add::operationType(FunctionParm& fp,
 | 
						|
                                                           CalpontSystemCatalog::ColType& resultType)
 | 
						|
{
 | 
						|
  resultType.colDataType = CalpontSystemCatalog::DATETIME;
 | 
						|
  resultType.colWidth = 8;
 | 
						|
 | 
						|
  return resultType;
 | 
						|
}
 | 
						|
 | 
						|
int64_t Func_date_add::getIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull,
 | 
						|
                                 CalpontSystemCatalog::ColType& ct)
 | 
						|
{
 | 
						|
  int64_t val = 0;
 | 
						|
  bool dateType = false;
 | 
						|
 | 
						|
  switch (parm[0]->data()->resultType().colDataType)
 | 
						|
  {
 | 
						|
    case execplan::CalpontSystemCatalog::BIGINT:
 | 
						|
    case execplan::CalpontSystemCatalog::INT:
 | 
						|
    case execplan::CalpontSystemCatalog::MEDINT:
 | 
						|
    case execplan::CalpontSystemCatalog::TINYINT:
 | 
						|
    case execplan::CalpontSystemCatalog::SMALLINT:
 | 
						|
    {
 | 
						|
      val = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case execplan::CalpontSystemCatalog::DECIMAL:
 | 
						|
    case execplan::CalpontSystemCatalog::UDECIMAL:
 | 
						|
    {
 | 
						|
      if (parm[0]->data()->resultType().scale == 0)
 | 
						|
        val = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull));
 | 
						|
      else
 | 
						|
        isNull = true;
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case execplan::CalpontSystemCatalog::VARCHAR:
 | 
						|
    case execplan::CalpontSystemCatalog::CHAR:
 | 
						|
    case execplan::CalpontSystemCatalog::TEXT:
 | 
						|
    {
 | 
						|
      val = dataconvert::DataConvert::stringToDatetime(parm[0]->data()->getStrVal(row, isNull).safeString(""));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case execplan::CalpontSystemCatalog::DATE:
 | 
						|
    {
 | 
						|
      val = parm[0]->data()->getDateIntVal(row, isNull);
 | 
						|
      dateType = true;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case execplan::CalpontSystemCatalog::DATETIME:
 | 
						|
    {
 | 
						|
      val = parm[0]->data()->getDatetimeIntVal(row, isNull);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case execplan::CalpontSystemCatalog::TIMESTAMP:
 | 
						|
    {
 | 
						|
      TimeStamp timestamp(parm[0]->data()->getTimestampIntVal(row, isNull));
 | 
						|
      int64_t seconds = timestamp.second;
 | 
						|
      MySQLTime m_time;
 | 
						|
      gmtSecToMySQLTime(seconds, m_time, ct.getTimeZone());
 | 
						|
      DateTime dt;
 | 
						|
      dt.year = m_time.year;
 | 
						|
      dt.month = m_time.month;
 | 
						|
      dt.day = m_time.day;
 | 
						|
      dt.hour = m_time.hour;
 | 
						|
      dt.minute = m_time.minute;
 | 
						|
      dt.second = m_time.second;
 | 
						|
      dt.msecond = timestamp.msecond;
 | 
						|
      val = *(reinterpret_cast<int64_t*>(&dt));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    default:
 | 
						|
    {
 | 
						|
      isNull = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (isNull || val == -1)
 | 
						|
  {
 | 
						|
    isNull = true;
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  IntervalColumn::interval_type unit =
 | 
						|
      static_cast<IntervalColumn::interval_type>(parm[2]->data()->getIntVal(row, isNull));
 | 
						|
  OpType funcType = OP_ADD;
 | 
						|
  ConstantColumn* constCol = dynamic_cast<ConstantColumn*>(parm[3]->data());
 | 
						|
  execplan::CalpontSystemCatalog::ColType ct3 = parm[3]->data()->resultType();
 | 
						|
 | 
						|
  if ((ct3.colDataType == execplan::CalpontSystemCatalog::CHAR ||
 | 
						|
       ct3.colDataType == execplan::CalpontSystemCatalog::TEXT ||
 | 
						|
       ct3.colDataType == execplan::CalpontSystemCatalog::VARCHAR) &&
 | 
						|
      constCol != NULL && constCol->constval().safeString().compare("SUB") == 0)
 | 
						|
    funcType = OP_SUB;
 | 
						|
  else
 | 
						|
    funcType = static_cast<OpType>(parm[3]->data()->getIntVal(row, isNull));
 | 
						|
 | 
						|
  uint64_t value = helpers::dateAdd(val, parm[1]->data()->getStrVal(row, isNull).safeString(""), unit, dateType, funcType);
 | 
						|
 | 
						|
  if (value == 0)
 | 
						|
    isNull = true;
 | 
						|
 | 
						|
  //	if (dateType)
 | 
						|
  //		value = (((value >> 32) & 0xFFFFFFC0) | 0x3E);
 | 
						|
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
string Func_date_add::getStrVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull,
 | 
						|
                                CalpontSystemCatalog::ColType& ct)
 | 
						|
{
 | 
						|
  return dataconvert::DataConvert::datetimeToString(getIntVal(row, parm, isNull, ct));
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace funcexp
 |