You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-07 03:22:57 +03:00
the begginning
This commit is contained in:
726
utils/funcexp/func_date_add.cpp
Normal file
726
utils/funcexp/func_date_add.cpp
Normal file
@@ -0,0 +1,726 @@
|
||||
/* 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] ) {
|
||||
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 ) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 funcexp::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:
|
||||
{
|
||||
if (parm[0]->data()->resultType().scale)
|
||||
val = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull));
|
||||
break;
|
||||
}
|
||||
case execplan::CalpontSystemCatalog::VARCHAR:
|
||||
case execplan::CalpontSystemCatalog::CHAR:
|
||||
{
|
||||
val = dataconvert::DataConvert::stringToDatetime(parm[0]->data()->getStrVal(row, isNull));
|
||||
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;
|
||||
}
|
||||
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::VARCHAR) &&
|
||||
constCol != NULL && constCol->constval().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), 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
|
||||
// vim:ts=4 sw=4:
|
Reference in New Issue
Block a user