You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
MCOL-4044: Add oracle mode functions.
This commit is contained in:
@ -3,6 +3,7 @@ include_directories( ${ENGINE_COMMON_INCLUDES} )
|
||||
|
||||
|
||||
########### next target ###############
|
||||
# func_decode_oracle.cpp
|
||||
|
||||
set(funcexp_LIB_SRCS
|
||||
functor.cpp
|
||||
@ -20,6 +21,7 @@ set(funcexp_LIB_SRCS
|
||||
func_char_length.cpp
|
||||
func_coalesce.cpp
|
||||
func_concat.cpp
|
||||
func_concat_oracle.cpp
|
||||
func_concat_ws.cpp
|
||||
func_conv.cpp
|
||||
func_crc32.cpp
|
||||
@ -31,6 +33,7 @@ set(funcexp_LIB_SRCS
|
||||
func_dayofweek.cpp
|
||||
func_dayofyear.cpp
|
||||
func_decode.cpp
|
||||
func_decode_oracle.cpp
|
||||
func_div.cpp
|
||||
func_elt.cpp
|
||||
func_encode.cpp
|
||||
@ -60,6 +63,7 @@ set(funcexp_LIB_SRCS
|
||||
func_length.cpp
|
||||
func_lpad.cpp
|
||||
func_ltrim.cpp
|
||||
func_ltrim_oracle.cpp
|
||||
func_makedate.cpp
|
||||
func_maketime.cpp
|
||||
func_math.cpp
|
||||
@ -79,11 +83,13 @@ set(funcexp_LIB_SRCS
|
||||
func_regexp.cpp
|
||||
func_repeat.cpp
|
||||
func_replace.cpp
|
||||
func_replace_oracle.cpp
|
||||
func_reverse.cpp
|
||||
func_right.cpp
|
||||
func_round.cpp
|
||||
func_rpad.cpp
|
||||
func_rtrim.cpp
|
||||
func_rtrim_oracle.cpp
|
||||
func_second.cpp
|
||||
func_sec_to_time.cpp
|
||||
func_sha.cpp
|
||||
@ -101,6 +107,7 @@ set(funcexp_LIB_SRCS
|
||||
func_timestampdiff.cpp
|
||||
func_to_days.cpp
|
||||
func_trim.cpp
|
||||
func_trim_oracle.cpp
|
||||
func_truncate.cpp
|
||||
func_ucase.cpp
|
||||
func_unhex.cpp
|
||||
|
78
utils/funcexp/func_concat_oracle.cpp
Normal file
78
utils/funcexp/func_concat_oracle.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 2021 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. */
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "functor_str.h"
|
||||
#include "functioncolumn.h"
|
||||
#include "utils_utf8.h"
|
||||
using namespace execplan;
|
||||
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "dataconvert.h"
|
||||
using namespace dataconvert;
|
||||
|
||||
namespace funcexp
|
||||
{
|
||||
|
||||
CalpontSystemCatalog::ColType Func_concat_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType )
|
||||
{
|
||||
// operation type is not used by this functor
|
||||
return fp[0]->data()->resultType();
|
||||
}
|
||||
|
||||
|
||||
// Returns the string that results from concatenating the arguments.
|
||||
// concat_oracle() returns NULL all arguments are NULL.
|
||||
// single arguments null is replaced by "".
|
||||
//
|
||||
string Func_concat_oracle::getStrVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType&)
|
||||
{
|
||||
string ret;
|
||||
string tmp;
|
||||
stringValue(parm[0], row, isNull, ret);
|
||||
// Oracle Mode should replace NULL with "" unless all values are NULL
|
||||
if (isNull)
|
||||
{
|
||||
ret = "";
|
||||
isNull = false;
|
||||
}
|
||||
// TODO: do a better job of cutting down the number re-allocations.
|
||||
// look at Item_func_concat::realloc_result for ideas and use
|
||||
// std::string:resize() appropriatly.
|
||||
for ( unsigned int id = 1 ; id < parm.size() ; id++)
|
||||
{
|
||||
stringValue(parm[id], row, isNull, tmp);
|
||||
if (isNull)
|
||||
{
|
||||
tmp = "";
|
||||
isNull = false;
|
||||
}
|
||||
ret.append(tmp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace funcexp
|
||||
// vim:ts=4 sw=4:
|
@ -1,3 +1,20 @@
|
||||
/* Copyright (C) 2021 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. */
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
585
utils/funcexp/func_decode_oracle.cpp
Normal file
585
utils/funcexp/func_decode_oracle.cpp
Normal file
@ -0,0 +1,585 @@
|
||||
/* Copyright (C) 2021 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. */
|
||||
|
||||
#include <string>
|
||||
//#define NDEBUG
|
||||
#include <cassert>
|
||||
using namespace std;
|
||||
|
||||
#include "functor_all.h"
|
||||
#include "functioncolumn.h"
|
||||
#include "predicateoperator.h"
|
||||
using namespace execplan;
|
||||
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "errorcodes.h"
|
||||
#include "idberrorinfo.h"
|
||||
#include "errorids.h"
|
||||
using namespace logging;
|
||||
|
||||
#include "utils_utf8.h"
|
||||
using namespace funcexp;
|
||||
|
||||
#include "collation.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace funcexp;
|
||||
|
||||
inline uint64_t simple_case_cmp(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = 0; // index to the parm list
|
||||
uint64_t n = 0; // remove expression from count of expression_i + result_i
|
||||
uint64_t hasElse = (parm.size() - 1) % 2; // if 1, then ELSE exist
|
||||
uint64_t whereCount = hasElse ? (parm.size() - 2) / 2 : (parm.size() - 1) / 2;
|
||||
bool foundIt = false;
|
||||
|
||||
switch (operationColType.colDataType)
|
||||
{
|
||||
case execplan::CalpontSystemCatalog::TINYINT:
|
||||
case execplan::CalpontSystemCatalog::SMALLINT:
|
||||
case execplan::CalpontSystemCatalog::MEDINT:
|
||||
case execplan::CalpontSystemCatalog::INT:
|
||||
case execplan::CalpontSystemCatalog::BIGINT:
|
||||
case execplan::CalpontSystemCatalog::DATE:
|
||||
{
|
||||
int64_t ev = parm[n]->data()->getIntVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getIntVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::DATETIME:
|
||||
{
|
||||
int64_t ev = parm[n]->data()->getDatetimeIntVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getDatetimeIntVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::TIMESTAMP:
|
||||
{
|
||||
int64_t ev = parm[n]->data()->getTimestampIntVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getTimestampIntVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::TIME:
|
||||
{
|
||||
int64_t ev = parm[n]->data()->getTimeIntVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getTimeIntVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case execplan::CalpontSystemCatalog::UBIGINT:
|
||||
case execplan::CalpontSystemCatalog::UINT:
|
||||
case execplan::CalpontSystemCatalog::UMEDINT:
|
||||
case execplan::CalpontSystemCatalog::UTINYINT:
|
||||
case execplan::CalpontSystemCatalog::USMALLINT:
|
||||
{
|
||||
uint64_t ev = parm[n]->data()->getUintVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getUintVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::CHAR:
|
||||
case execplan::CalpontSystemCatalog::TEXT:
|
||||
case execplan::CalpontSystemCatalog::VARCHAR:
|
||||
{
|
||||
const string& ev = parm[n]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
break;
|
||||
CHARSET_INFO* cs = parm[n]->data()->resultType().getCharset();
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
//BUG 5362
|
||||
const string& p1 = parm[i]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
break;
|
||||
if (cs->strnncoll(ev.c_str(), ev.length(), p1.c_str(), p1.length()) == 0)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
{
|
||||
IDB_Decimal ev = parm[n]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getDecimalVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::DOUBLE:
|
||||
case execplan::CalpontSystemCatalog::UDOUBLE:
|
||||
{
|
||||
double ev = parm[n]->data()->getDoubleVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getDoubleVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::FLOAT:
|
||||
case execplan::CalpontSystemCatalog::UFLOAT:
|
||||
{
|
||||
float ev = parm[n]->data()->getFloatVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getFloatVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case execplan::CalpontSystemCatalog::LONGDOUBLE:
|
||||
{
|
||||
long double ev = parm[n]->data()->getLongDoubleVal(row, isNull);
|
||||
|
||||
if (isNull)
|
||||
break;
|
||||
|
||||
for (i = 1; i <= whereCount; i++)
|
||||
{
|
||||
if (ev == parm[i]->data()->getLongDoubleVal(row, isNull) && !isNull)
|
||||
{
|
||||
foundIt = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "case: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
|
||||
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundIt && !hasElse)
|
||||
isNull = true;
|
||||
else if (!foundIt && hasElse && !isNull)
|
||||
{
|
||||
i = parm.size() - 1;
|
||||
}
|
||||
else if (isNull && hasElse)
|
||||
// BUG 5110. Only way we can exit above with isNull == true is when ev is NULL
|
||||
// if so and we have else condition we need to use it by setting i = else
|
||||
{
|
||||
i = parm.size() - 1;
|
||||
isNull = false;
|
||||
}
|
||||
|
||||
if (foundIt)
|
||||
{
|
||||
i += whereCount;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp,
|
||||
CalpontSystemCatalog::ColType& resultType,
|
||||
bool simpleCase)
|
||||
{
|
||||
uint64_t simple = simpleCase ? 1 : 0;
|
||||
bool hasElse = (((fp.size()-simple) % 2) != 0); // if 1, then ELSE exist
|
||||
|
||||
uint64_t parmCount = hasElse ? (fp.size() - 2) : (fp.size() - 1);
|
||||
uint64_t whereCount = hasElse ? (fp.size() - 2 + simple) / 2 : (fp.size() - 1) / 2 + simple;
|
||||
|
||||
bool allStringO = true;
|
||||
bool allStringR = true;
|
||||
|
||||
FunctionParm::size_type l = fp.size() - 1; // last fp index
|
||||
idbassert(fp[l]->data());
|
||||
CalpontSystemCatalog::ColType oct = fp[l]->data()->resultType();
|
||||
CalpontSystemCatalog::ColType rct = resultType;
|
||||
bool operation = true;
|
||||
|
||||
for (uint64_t i = 0; i <= parmCount; i++)
|
||||
{
|
||||
// for SimpleCase, we return the type of the case expression,
|
||||
// which will always be in position 0.
|
||||
if (i == 0 && simpleCase)
|
||||
{
|
||||
if (fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::CHAR &&
|
||||
fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::TEXT &&
|
||||
fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::VARCHAR)
|
||||
{
|
||||
PredicateOperator op;
|
||||
op.setOpType(oct, fp[i]->data()->resultType());
|
||||
allStringO = false;
|
||||
oct = op.operationType();
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// operation or result type
|
||||
operation = ((i > 0+simple) && (i <= whereCount));
|
||||
|
||||
if (fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::CHAR &&
|
||||
fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::TEXT &&
|
||||
fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::VARCHAR)
|
||||
{
|
||||
// this is not a string column
|
||||
PredicateOperator op;
|
||||
|
||||
if (operation)
|
||||
{
|
||||
if (!simpleCase)
|
||||
{
|
||||
op.setOpType(oct, fp[i]->data()->resultType());
|
||||
allStringO = false;
|
||||
oct = op.operationType();
|
||||
}
|
||||
}
|
||||
|
||||
// If any parm is of string type, the result type should be string. (same as if)
|
||||
else if (rct.colDataType != CalpontSystemCatalog::CHAR &&
|
||||
rct.colDataType != CalpontSystemCatalog::TEXT &&
|
||||
rct.colDataType != CalpontSystemCatalog::VARCHAR)
|
||||
{
|
||||
op.setOpType(rct, fp[i]->data()->resultType());
|
||||
allStringR = false;
|
||||
rct = op.operationType();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is a string
|
||||
// If any parm is of string type, the result type should be string. (same as if)
|
||||
allStringR = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (allStringO)
|
||||
{
|
||||
oct.colDataType = CalpontSystemCatalog::VARCHAR;
|
||||
oct.colWidth = 255;
|
||||
}
|
||||
|
||||
if (allStringR)
|
||||
{
|
||||
rct.colDataType = CalpontSystemCatalog::VARCHAR;
|
||||
rct.colWidth = 255;
|
||||
}
|
||||
|
||||
if (rct.scale != 0 && rct.colDataType == CalpontSystemCatalog::BIGINT)
|
||||
rct.colDataType = CalpontSystemCatalog::DECIMAL;
|
||||
|
||||
if (oct.scale != 0 && oct.colDataType == CalpontSystemCatalog::BIGINT)
|
||||
oct.colDataType = CalpontSystemCatalog::DECIMAL;
|
||||
|
||||
resultType = rct;
|
||||
return oct;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace funcexp
|
||||
{
|
||||
|
||||
// simple CASE:
|
||||
// SELECT CASE ("expression")
|
||||
// WHEN "condition1" THEN "result1"
|
||||
// WHEN "condition2" THEN "result2"
|
||||
// ...
|
||||
// [ELSE "resultN"]
|
||||
// END
|
||||
//
|
||||
// simple CASE parm order:
|
||||
// expression condition1 condition2 ... result1 result2 ... [resultN]
|
||||
//
|
||||
// Note that this order changed in 10.2.14, see MCOL-1341
|
||||
|
||||
CalpontSystemCatalog::ColType Func_decode_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
|
||||
{
|
||||
return caseOperationType(fp, resultType, true);
|
||||
}
|
||||
|
||||
|
||||
bool Func_decode_oracle::getBoolVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, operationColType);
|
||||
|
||||
if (isNull)
|
||||
return false;
|
||||
|
||||
ParseTree* lop = parm[i]->left();
|
||||
ParseTree* rop = parm[i]->right();
|
||||
if (lop && rop)
|
||||
{
|
||||
return (reinterpret_cast<Operator*>(parm[i]->data()))->getBoolVal(row, isNull, lop, rop);
|
||||
}
|
||||
|
||||
return parm[i]->data()->getBoolVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
int64_t Func_decode_oracle::getIntVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, operationColType);
|
||||
|
||||
if (isNull)
|
||||
return joblist::BIGINTNULL;
|
||||
|
||||
return parm[i]->data()->getIntVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
string Func_decode_oracle::getStrVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, operationColType);
|
||||
|
||||
if (isNull)
|
||||
return string("");
|
||||
|
||||
return parm[i]->data()->getStrVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
IDB_Decimal Func_decode_oracle::getDecimalVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, operationColType);
|
||||
|
||||
if (isNull)
|
||||
return IDB_Decimal(); // need a null value for IDB_Decimal??
|
||||
|
||||
return parm[i]->data()->getDecimalVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
double Func_decode_oracle::getDoubleVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, operationColType);
|
||||
|
||||
if (isNull)
|
||||
return doubleNullVal();
|
||||
|
||||
return parm[i]->data()->getDoubleVal(row, isNull);
|
||||
}
|
||||
|
||||
long double Func_decode_oracle::getLongDoubleVal(Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, operationColType);
|
||||
|
||||
if (isNull)
|
||||
return doubleNullVal();
|
||||
|
||||
return parm[i]->data()->getLongDoubleVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
int32_t Func_decode_oracle::getDateIntVal(rowgroup::Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, op_ct);
|
||||
|
||||
if (isNull)
|
||||
return joblist::DATENULL;
|
||||
|
||||
return parm[i]->data()->getDateIntVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
int64_t Func_decode_oracle::getDatetimeIntVal(rowgroup::Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, op_ct);
|
||||
|
||||
if (isNull)
|
||||
return joblist::DATETIMENULL;
|
||||
|
||||
return parm[i]->data()->getDatetimeIntVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
int64_t Func_decode_oracle::getTimestampIntVal(rowgroup::Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, op_ct);
|
||||
|
||||
if (isNull)
|
||||
return joblist::TIMESTAMPNULL;
|
||||
|
||||
return parm[i]->data()->getTimestampIntVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
int64_t Func_decode_oracle::getTimeIntVal(rowgroup::Row& row,
|
||||
FunctionParm& parm,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct)
|
||||
{
|
||||
uint64_t i = simple_case_cmp(row, parm, isNull, op_ct);
|
||||
|
||||
if (isNull)
|
||||
return joblist::TIMENULL;
|
||||
|
||||
return parm[i]->data()->getTimeIntVal(row, isNull);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
/* Copyright (C) 2014 InfiniDB, Inc.
|
||||
Copyright (C) 2021 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. */
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
107
utils/funcexp/func_ltrim_oracle.cpp
Normal file
107
utils/funcexp/func_ltrim_oracle.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/* 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_ltrim.cpp 3923 2013-06-19 21:43:06Z bwilkinson $
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "functor_str.h"
|
||||
#include "functioncolumn.h"
|
||||
#include "utils_utf8.h"
|
||||
using namespace execplan;
|
||||
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "joblisttypes.h"
|
||||
using namespace joblist;
|
||||
|
||||
#include "collation.h"
|
||||
|
||||
namespace funcexp
|
||||
{
|
||||
|
||||
CalpontSystemCatalog::ColType Func_ltrim_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
|
||||
{
|
||||
// operation type is not used by this functor
|
||||
return fp[0]->data()->resultType();
|
||||
}
|
||||
|
||||
|
||||
std::string Func_ltrim_oracle::getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& type)
|
||||
{
|
||||
CHARSET_INFO* cs = type.getCharset();
|
||||
// The original string
|
||||
const string& src = fp[0]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
return "";
|
||||
if (src.empty() || src.length() == 0)
|
||||
return src;
|
||||
// binLen represents the number of bytes in src
|
||||
size_t binLen = src.length();
|
||||
const char* pos = src.c_str();
|
||||
const char* end = pos + binLen;
|
||||
// strLen = the number of characters in src
|
||||
size_t strLen = cs->numchars(pos, end);
|
||||
|
||||
// The trim characters.
|
||||
const string& trim = (fp.size() > 1 ? fp[1]->data()->getStrVal(row, isNull) : " ");
|
||||
// binTLen represents the number of bytes in trim
|
||||
size_t binTLen = trim.length();
|
||||
const char* posT = trim.c_str();
|
||||
// strTLen = the number of characters in trim
|
||||
size_t strTLen = cs->numchars(posT, posT+binTLen);
|
||||
if (strTLen == 0 || strTLen > strLen)
|
||||
return src;
|
||||
|
||||
if (binTLen == 1)
|
||||
{
|
||||
// If the trim string is 1 byte, don't waste cpu for memcmp
|
||||
while (pos < end && *pos == *posT)
|
||||
{
|
||||
++pos;
|
||||
--binLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (pos+binTLen <= end && memcmp(pos,posT,binTLen) == 0)
|
||||
{
|
||||
pos += binTLen;
|
||||
binLen -= binTLen;
|
||||
}
|
||||
}
|
||||
// Turn back to a string
|
||||
std::string ret(pos, binLen);
|
||||
if (binLen == 0)
|
||||
{
|
||||
isNull = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace funcexp
|
||||
// vim:ts=4 sw=4:
|
||||
|
178
utils/funcexp/func_replace_oracle.cpp
Normal file
178
utils/funcexp/func_replace_oracle.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/* Copyright (C) 2021 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. */
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "functor_str.h"
|
||||
#include "functioncolumn.h"
|
||||
using namespace execplan;
|
||||
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "joblisttypes.h"
|
||||
using namespace joblist;
|
||||
|
||||
#include "collation.h"
|
||||
|
||||
namespace funcexp
|
||||
{
|
||||
|
||||
CalpontSystemCatalog::ColType Func_replace_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
|
||||
{
|
||||
// operation type is not used by this functor
|
||||
return fp[0]->data()->resultType();
|
||||
}
|
||||
|
||||
|
||||
std::string Func_replace_oracle::getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& ct)
|
||||
{
|
||||
CHARSET_INFO* cs = ct.getCharset();
|
||||
|
||||
const string& str = fp[0]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
return "";
|
||||
size_t strLen = str.length();
|
||||
|
||||
const string& fromstr = fp[1]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
return "";
|
||||
if (fromstr.length() == 0)
|
||||
return str;
|
||||
size_t fromLen = fromstr.length();
|
||||
|
||||
const string& tostr = fp[2]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
return "";
|
||||
size_t toLen = tostr.length();
|
||||
|
||||
bool binaryCmp = (cs->state & MY_CS_BINSORT) || !cs->use_mb();
|
||||
string newstr;
|
||||
size_t pos = 0;
|
||||
if (binaryCmp)
|
||||
{
|
||||
// Count the number of fromstr in strend so we can reserve buffer space.
|
||||
int count = 0;
|
||||
do
|
||||
{
|
||||
++count;
|
||||
pos = str.find(fromstr, pos + fromLen);
|
||||
}
|
||||
while (pos != string::npos);
|
||||
|
||||
newstr.reserve(strLen + (count * ((int)toLen - (int)fromLen)) + 1);
|
||||
|
||||
uint32_t i = 0;
|
||||
pos = str.find(fromstr);
|
||||
if (pos == string::npos)
|
||||
return str;
|
||||
// Move the stuff into newstr
|
||||
do
|
||||
{
|
||||
if (pos > i)
|
||||
newstr = newstr + str.substr(i, pos - i);
|
||||
|
||||
newstr = newstr + tostr;
|
||||
i = pos + fromLen;
|
||||
pos = str.find(fromstr, i);
|
||||
}
|
||||
while (pos != string::npos);
|
||||
|
||||
newstr = newstr + str.substr(i, string::npos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// UTF
|
||||
const char* src = str.c_str();
|
||||
const char* srcEnd = src + strLen;
|
||||
const char* srchEnd = srcEnd - fromLen + 1;
|
||||
const char* from = fromstr.c_str();
|
||||
const char* fromEnd = from + fromLen;
|
||||
const char* to = tostr.c_str();
|
||||
const char* ptr = src;
|
||||
char *i,*j;
|
||||
size_t count = 10; // Some arbitray number to reserve some space to start.
|
||||
int growlen = (int)toLen - (int)fromLen;
|
||||
growlen = growlen < 1 ? 1 : growlen;
|
||||
growlen *= count;
|
||||
newstr.reserve(strLen + (count * growlen) + 1);
|
||||
size_t maxsize = newstr.capacity();
|
||||
uint32_t l;
|
||||
|
||||
// We don't know where byte patterns might match so
|
||||
// we start at the beginning of the string and move forward
|
||||
// one character at a time until we find a match. Then we can
|
||||
// move the src bytes and add in the to bytes,then try again.
|
||||
while (ptr < srchEnd)
|
||||
{
|
||||
bool found = false;
|
||||
if (*ptr == *from) // If the first byte matches, maybe we have a match
|
||||
{
|
||||
// Do a byte by byte compare of src at that spot against from
|
||||
i = const_cast<char*>(ptr) + 1;
|
||||
j = const_cast<char*>(from) + 1;
|
||||
found = true;
|
||||
while (j != fromEnd)
|
||||
{
|
||||
if (*i++ != *j++)
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
if (ptr < i)
|
||||
{
|
||||
int mvsize = ptr - src;
|
||||
if (newstr.length() + mvsize + toLen > maxsize)
|
||||
{
|
||||
// We need a re-alloc
|
||||
newstr.reserve(maxsize + growlen);
|
||||
maxsize = newstr.capacity();
|
||||
growlen *= 2;
|
||||
}
|
||||
newstr.append(src, ptr - src);
|
||||
src += mvsize + fromLen;
|
||||
ptr = src;
|
||||
}
|
||||
newstr.append(to, toLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
// move to the next character
|
||||
if ((l = my_ismbchar(cs, ptr, srcEnd))) // returns the number of bytes in the leading char or zero if one byte
|
||||
ptr += l;
|
||||
else
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
// Copy in the trailing src chars.
|
||||
newstr.append(src, srcEnd - src);
|
||||
}
|
||||
return newstr;
|
||||
}
|
||||
|
||||
|
||||
} // namespace funcexp
|
||||
// vim:ts=4 sw=4:
|
||||
|
169
utils/funcexp/func_rtrim_oracle.cpp
Normal file
169
utils/funcexp/func_rtrim_oracle.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/* 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_rtrim.cpp 3923 2013-06-19 21:43:06Z bwilkinson $
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "functor_str.h"
|
||||
#include "functioncolumn.h"
|
||||
#include "utils_utf8.h"
|
||||
using namespace execplan;
|
||||
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "joblisttypes.h"
|
||||
using namespace joblist;
|
||||
|
||||
#include "collation.h"
|
||||
|
||||
namespace funcexp
|
||||
{
|
||||
|
||||
CalpontSystemCatalog::ColType Func_rtrim_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
|
||||
{
|
||||
// operation type is not used by this functor
|
||||
return fp[0]->data()->resultType();
|
||||
}
|
||||
|
||||
|
||||
std::string Func_rtrim_oracle::getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& type)
|
||||
{
|
||||
CHARSET_INFO* cs = type.getCharset();
|
||||
// The original string
|
||||
const string& src = fp[0]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
return "";
|
||||
if (src.empty() || src.length() == 0)
|
||||
return src;
|
||||
// binLen represents the number of bytes in src
|
||||
size_t binLen = src.length();
|
||||
const char* pos = src.c_str();
|
||||
const char* end = pos + binLen;
|
||||
// strLen = the number of characters in src
|
||||
size_t strLen = cs->numchars(pos, end);
|
||||
|
||||
// The trim characters.
|
||||
const string& trim = (fp.size() > 1 ? fp[1]->data()->getStrVal(row, isNull) : " ");
|
||||
// binTLen represents the number of bytes in trim
|
||||
size_t binTLen = trim.length();
|
||||
const char* posT = trim.c_str();
|
||||
// strTLen = the number of characters in trim
|
||||
size_t strTLen = cs->numchars(posT, posT+binTLen);
|
||||
if (strTLen == 0 || strTLen > strLen)
|
||||
return src;
|
||||
|
||||
if (binTLen == 1)
|
||||
{
|
||||
const char* ptr = pos;
|
||||
if (cs->use_mb()) // This is a multi-byte charset
|
||||
{
|
||||
const char* p = pos;
|
||||
uint32 l;
|
||||
// Multibyte characters in the string give us alignment problems
|
||||
// What we do here is skip past any multibyte characters. Whn
|
||||
// don with this loop, ptr is pointing to a singlebyte char that
|
||||
// is after all multibyte chars in the string, or to end.
|
||||
while (ptr < end)
|
||||
{
|
||||
if ((l = my_ismbchar(cs, ptr, end))) // returns the number of bytes in the leading char or zero if one byte
|
||||
{
|
||||
ptr += l;
|
||||
p = ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
ptr = p;
|
||||
}
|
||||
while (ptr < end && end[-1] == *posT)
|
||||
{
|
||||
--end;
|
||||
--binLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// An uncommon case where the space character is > 1 byte
|
||||
if (cs->use_mb()) // This is a multi-byte charset
|
||||
{
|
||||
// The problem is that the byte pattern at the end could
|
||||
// match memcmp, but not be correct since the first byte compared
|
||||
// may actually be a second or later byte from a previous char.
|
||||
|
||||
// We start at the beginning of the string and move forward
|
||||
// one character at a time until we reach the end. Then we can
|
||||
// safely compare and remove on character. Then back to the beginning
|
||||
// and try again.
|
||||
while (end - binTLen >= pos)
|
||||
{
|
||||
const char* p = pos;
|
||||
uint32 l;
|
||||
while (p + binTLen < end)
|
||||
{
|
||||
if ((l = my_ismbchar(cs, p, end))) // returns the number of bytes in the leading char or zero if one byte
|
||||
p += l;
|
||||
else
|
||||
++p;
|
||||
}
|
||||
if (p + binTLen == end && memcmp(p,posT,binTLen) == 0)
|
||||
{
|
||||
end -= binTLen;
|
||||
binLen -= binTLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // We've run out of places to look
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This implies we have a single byte charset and a multibyte
|
||||
// space character.
|
||||
// Should never get here, since rtrim only trims space characters
|
||||
// Included for completeness.
|
||||
while (end-binTLen >= pos && memcmp(end-binTLen,posT,binTLen) == 0)
|
||||
{
|
||||
end -= binTLen;
|
||||
binLen -= binTLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Turn back to a string
|
||||
std::string ret(pos, binLen);
|
||||
if (binLen == 0)
|
||||
{
|
||||
isNull = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace funcexp
|
||||
// vim:ts=4 sw=4:
|
||||
|
175
utils/funcexp/func_trim_oracle.cpp
Normal file
175
utils/funcexp/func_trim_oracle.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
/* Copyright (C) 2021 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. */
|
||||
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "functor_str.h"
|
||||
#include "functioncolumn.h"
|
||||
#include "utils_utf8.h"
|
||||
using namespace execplan;
|
||||
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "joblisttypes.h"
|
||||
using namespace joblist;
|
||||
|
||||
#include "collation.h"
|
||||
|
||||
namespace funcexp
|
||||
{
|
||||
CalpontSystemCatalog::ColType Func_trim_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
|
||||
{
|
||||
// operation type is not used by this functor
|
||||
return fp[0]->data()->resultType();
|
||||
}
|
||||
|
||||
|
||||
std::string Func_trim_oracle::getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& type)
|
||||
{
|
||||
CHARSET_INFO* cs = type.getCharset();
|
||||
// The original string
|
||||
const string& src = fp[0]->data()->getStrVal(row, isNull);
|
||||
if (isNull)
|
||||
return "";
|
||||
if (src.empty() || src.length() == 0)
|
||||
return src;
|
||||
// binLen represents the number of bytes in src
|
||||
size_t binLen = src.length();
|
||||
const char* pos = src.c_str();
|
||||
const char* end = pos + binLen;
|
||||
// strLen = the number of characters in src
|
||||
size_t strLen = cs->numchars(pos, end);
|
||||
|
||||
// The trim characters.
|
||||
const string& trim = (fp.size() > 1 ? fp[1]->data()->getStrVal(row, isNull) : " ");
|
||||
// binTLen represents the number of bytes in trim
|
||||
size_t binTLen = trim.length();
|
||||
const char* posT = trim.c_str();
|
||||
// strTLen = the number of characters in trim
|
||||
size_t strTLen = cs->numchars(posT, posT+binTLen);
|
||||
if (strTLen == 0 || strTLen > strLen)
|
||||
return src;
|
||||
|
||||
if (binTLen == 1)
|
||||
{
|
||||
// If the trim string is 1 byte, don't waste cpu for memcmp
|
||||
// Trim leading
|
||||
while (pos < end && *pos == *posT)
|
||||
{
|
||||
++pos;
|
||||
--binLen;
|
||||
}
|
||||
// Trim trailing
|
||||
const char* ptr = pos;
|
||||
if (cs->use_mb()) // This is a multi-byte charset
|
||||
{
|
||||
const char* p = pos;
|
||||
uint32 l;
|
||||
// Multibyte characters in the string give us alignment problems
|
||||
// What we do here is skip past any multibyte characters. Whn
|
||||
// don with this loop, ptr is pointing to a singlebyte char that
|
||||
// is after all multibyte chars in the string, or to end.
|
||||
while (ptr < end)
|
||||
{
|
||||
if ((l = my_ismbchar(cs, ptr, end))) // returns the number of bytes in the leading char or zero if one byte
|
||||
{
|
||||
ptr += l;
|
||||
p = ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
ptr = p;
|
||||
}
|
||||
while (ptr < end && end[-1] == *posT)
|
||||
{
|
||||
--end;
|
||||
--binLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trim leading is easy
|
||||
while (pos+binTLen <= end && memcmp(pos,posT,binTLen) == 0)
|
||||
{
|
||||
pos += binTLen;
|
||||
binLen -= binTLen;
|
||||
}
|
||||
|
||||
// Trim trailing
|
||||
if (cs->use_mb()) // This is a multi-byte charset
|
||||
{
|
||||
// The problem is that the byte pattern at the end could
|
||||
// match memcmp, but not be correct since the first byte compared
|
||||
// may actually be a second or later byte from a previous char.
|
||||
|
||||
// We start at the beginning of the string and move forward
|
||||
// one character at a time until we reach the end. Then we can
|
||||
// safely compare and remove one character. Then back to the beginning
|
||||
// and try again.
|
||||
while (end - binTLen >= pos)
|
||||
{
|
||||
const char* p = pos;
|
||||
uint32_t l;
|
||||
while (p + binTLen < end)
|
||||
{
|
||||
if ((l = my_ismbchar(cs, p, end))) // returns the number of bytes in the leading char or zero if one byte
|
||||
p += l;
|
||||
else
|
||||
++p;
|
||||
}
|
||||
if (p + binTLen == end && memcmp(p,posT,binTLen) == 0)
|
||||
{
|
||||
end -= binTLen;
|
||||
binLen -= binTLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // We've run out of places to look
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (end-binTLen >= pos && memcmp(end-binTLen,posT,binTLen) == 0)
|
||||
{
|
||||
end -= binTLen;
|
||||
binLen -= binTLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Turn back to a string
|
||||
std::string ret(pos, binLen);
|
||||
if (binLen == 0)
|
||||
{
|
||||
isNull = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
} // namespace funcexp
|
||||
// vim:ts=4 sw=4:
|
||||
|
@ -97,6 +97,7 @@ FuncExp::FuncExp()
|
||||
fFuncMap["char_length"] = new Func_char_length(); //dlh
|
||||
fFuncMap["character_length"] = new Func_char_length(); //dlh
|
||||
fFuncMap["coalesce"] = new Func_coalesce();
|
||||
fFuncMap["concat_operator_oracle"] = new Func_concat_oracle();
|
||||
fFuncMap["concat"] = new Func_concat();
|
||||
fFuncMap["concat_ws"] = new Func_concat_ws();
|
||||
fFuncMap["conv"] = new Func_conv();
|
||||
@ -112,6 +113,7 @@ FuncExp::FuncExp()
|
||||
fFuncMap["dayofweek"] = new Func_dayofweek(); //dlh
|
||||
fFuncMap["dayofyear"] = new Func_dayofyear(); //dlh
|
||||
fFuncMap["decode"] = new Func_decode(); // BT
|
||||
fFuncMap["decode_oracle"] = new Func_decode_oracle(); // BT
|
||||
fFuncMap["degrees"] = new Func_degrees();
|
||||
fFuncMap["DIV"] = new Func_div(); // MySQL use upper case for this function name
|
||||
fFuncMap["elt"] = new Func_elt();
|
||||
@ -156,6 +158,7 @@ FuncExp::FuncExp()
|
||||
fFuncMap["lower"] = new Func_lcase(); //dlh
|
||||
fFuncMap["lpad"] = new Func_lpad(); //dlh
|
||||
fFuncMap["ltrim"] = new Func_ltrim(); //dlh
|
||||
fFuncMap["ltrim_oracle"] = new Func_ltrim_oracle(); //dlh
|
||||
fFuncMap["makedate"] = new Func_makedate();
|
||||
fFuncMap["maketime"] = new Func_maketime();
|
||||
fFuncMap["microsecond"] = new Func_microsecond();
|
||||
@ -183,11 +186,13 @@ FuncExp::FuncExp()
|
||||
fFuncMap["regexp"] = new Func_regexp(); //dlh
|
||||
fFuncMap["repeat"] = new Func_repeat(); //dlh
|
||||
fFuncMap["replace"] = new Func_replace(); //dlh
|
||||
fFuncMap["replace_oracle"] = new Func_replace_oracle(); //dlh
|
||||
fFuncMap["reverse"] = new Func_reverse(); //dlh
|
||||
fFuncMap["right"] = new Func_right(); //dlh
|
||||
fFuncMap["round"] = new Func_round();
|
||||
fFuncMap["rpad"] = new Func_rpad(); //dlh
|
||||
fFuncMap["rtrim"] = new Func_rtrim(); //dlh
|
||||
fFuncMap["rtrim_oracle"] = new Func_rtrim_oracle(); //dlh
|
||||
fFuncMap["second"] = new Func_second(); //dlh
|
||||
fFuncMap["sec_to_time"] = new Func_sec_to_time();
|
||||
fFuncMap["sha"] = new Func_sha();
|
||||
@ -210,6 +215,7 @@ FuncExp::FuncExp()
|
||||
fFuncMap["time_to_sec"] = new Func_time_to_sec(); //dlh
|
||||
fFuncMap["to_days"] = new Func_to_days(); //dlh
|
||||
fFuncMap["trim"] = new Func_trim(); //dlh
|
||||
fFuncMap["trim_oracle"] = new Func_trim_oracle(); //dlh
|
||||
fFuncMap["truncate"] = new Func_truncate(); //dlh
|
||||
fFuncMap["ucase"] = new Func_ucase(); //dlh
|
||||
fFuncMap["unhex"] = new Func_unhex();
|
||||
|
@ -122,6 +122,65 @@ public:
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
class Func_decode_oracle : public Func_All
|
||||
{
|
||||
public:
|
||||
Func_decode_oracle(): Func_All("decode_oracle") {}
|
||||
virtual ~Func_decode_oracle() {}
|
||||
|
||||
execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType);
|
||||
|
||||
bool getBoolVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
int64_t getIntVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
double getDoubleVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
long double getLongDoubleVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
std::string getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
int32_t getDateIntVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
int64_t getDatetimeIntVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
int64_t getTimestampIntVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
|
||||
int64_t getTimeIntVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
|
||||
/** @brief Func_searched_case class
|
||||
*/
|
||||
|
@ -183,6 +183,22 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** @brief Func_concat_oracle class
|
||||
*/
|
||||
class Func_concat_oracle : public Func_Str
|
||||
{
|
||||
public:
|
||||
Func_concat_oracle() : Func_Str("concat_operator_oracle") {}
|
||||
virtual ~Func_concat_oracle() {}
|
||||
|
||||
execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType);
|
||||
|
||||
std::string getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
/** @brief Func_substr class
|
||||
*/
|
||||
class Func_substr : public Func_Str
|
||||
@ -333,6 +349,55 @@ public:
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
/** @brief Func_ltrim class
|
||||
*/
|
||||
class Func_ltrim_oracle : public Func_Str
|
||||
{
|
||||
public:
|
||||
Func_ltrim_oracle() : Func_Str("ltrim_oracle") {}
|
||||
virtual ~Func_ltrim_oracle() {}
|
||||
|
||||
execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType);
|
||||
|
||||
std::string getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
|
||||
/** @brief Func_rtrim class
|
||||
*/
|
||||
class Func_rtrim_oracle : public Func_Str
|
||||
{
|
||||
public:
|
||||
Func_rtrim_oracle() : Func_Str("rtrim_oracle") {}
|
||||
virtual ~Func_rtrim_oracle() {}
|
||||
|
||||
execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType);
|
||||
|
||||
std::string getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
|
||||
/** @brief Func_trim class
|
||||
*/
|
||||
class Func_trim_oracle : public Func_Str
|
||||
{
|
||||
public:
|
||||
Func_trim_oracle() : Func_Str("trim_oracle") {}
|
||||
virtual ~Func_trim_oracle() {}
|
||||
|
||||
execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType);
|
||||
|
||||
std::string getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
/** @brief Func_lpad class
|
||||
*/
|
||||
@ -386,6 +451,19 @@ public:
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
class Func_replace_oracle : public Func_Str
|
||||
{
|
||||
public:
|
||||
Func_replace_oracle() : Func_Str("replace_oracle") {}
|
||||
virtual ~Func_replace_oracle() {}
|
||||
|
||||
execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType);
|
||||
|
||||
std::string getStrVal(rowgroup::Row& row,
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
};
|
||||
|
||||
/** @brief Func_right class
|
||||
*/
|
||||
|
Reference in New Issue
Block a user