提交 c8dee21d 编写于 作者: H hustjieke

feat: rm files after rebase leftover #1217

files deleted:
        storage/tianmu/core/rc_attr_typeinfo.h
        storage/tianmu/handler/tianmu_handler.cpp
        storage/tianmu/handler/tianmu_handler_com.cpp
        storage/tianmu/types/rc_data_types.cpp
        storage/tianmu/types/rc_num.cpp
        storage/tianmu/types/rc_num.h
        storage/tianmu/types/rc_value_object.cpp
上级 6efc206e
/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved.
Use is subject to license terms
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-1335 USA
*/
#ifndef TIANMU_CORE_RC_ATTR_TYPEINFO_H_
#define TIANMU_CORE_RC_ATTR_TYPEINFO_H_
#pragma once
#include <bitset>
#include "common/common_definitions.h"
namespace Tianmu {
namespace types {
class RCDataType;
} // namespace types
namespace core {
class ATI {
public:
static int TextSize(common::CT attrt, uint precision, int scale, DTCollation col = DTCollation());
static bool IsInteger32Type(common::CT attr_type) {
return attr_type == common::CT::INT || attr_type == common::CT::BYTEINT || attr_type == common::CT::SMALLINT ||
attr_type == common::CT::MEDIUMINT;
}
static bool IsIntegerType(common::CT attr_type) {
return IsInteger32Type(attr_type) || attr_type == common::CT::BIGINT;
}
static bool IsFixedNumericType(common::CT attr_type) {
return IsInteger32Type(attr_type) || attr_type == common::CT::BIGINT || attr_type == common::CT::NUM;
}
static bool IsRealType(common::CT attr_type) {
return attr_type == common::CT::FLOAT || attr_type == common::CT::REAL;
}
static bool IsNumericType(common::CT attr_type) {
return IsInteger32Type(attr_type) || attr_type == common::CT::BIGINT || attr_type == common::CT::NUM ||
attr_type == common::CT::FLOAT || attr_type == common::CT::REAL;
}
static bool IsBinType(common::CT attr_type) {
return attr_type == common::CT::BYTE || attr_type == common::CT::VARBYTE || attr_type == common::CT::BIN;
}
static bool IsTxtType(common::CT attr_type) {
return attr_type == common::CT::STRING || attr_type == common::CT::VARCHAR || attr_type == common::CT::LONGTEXT;
}
static bool IsCharType(common::CT attr_type) { return attr_type == common::CT::STRING; }
static bool IsStringType(common::CT attr_type) {
return attr_type == common::CT::STRING || attr_type == common::CT::VARCHAR || attr_type == common::CT::LONGTEXT ||
IsBinType(attr_type);
}
static bool IsDateTimeType(common::CT attr_type) {
return attr_type == common::CT::DATE || attr_type == common::CT::TIME || attr_type == common::CT::YEAR ||
attr_type == common::CT::DATETIME || attr_type == common::CT::TIMESTAMP;
}
static bool IsDateTimeNType(common::CT attr_type) {
return attr_type == common::CT::TIME_N || attr_type == common::CT::DATETIME_N ||
attr_type == common::CT::TIMESTAMP_N;
}
};
class AttributeTypeInfo {
public:
enum class enumATI {
NOT_NULL = 0,
AUTO_INC = 1,
BLOOM_FILTER = 2,
};
AttributeTypeInfo(common::CT attrt, bool notnull, uint precision = 0, ushort scale = 0, bool auto_inc = false,
DTCollation collation = DTCollation(), common::PackFmt fmt = common::PackFmt::DEFAULT,
bool filter = false)
: attrt(attrt), fmt(fmt), precision(precision), scale(scale), collation(collation) {
flag[static_cast<int>(enumATI::NOT_NULL)] = notnull;
flag[static_cast<int>(enumATI::BLOOM_FILTER)] = filter;
flag[static_cast<int>(enumATI::AUTO_INC)] = auto_inc;
// lookup only applies to string type
if (attrt != common::CT::STRING && attrt != common::CT::VARCHAR && Lookup())
fmt = common::PackFmt::DEFAULT;
}
common::CT Type() const { return attrt; }
common::PackType GetPackType() const {
return ATI::IsDateTimeType(attrt) || ATI::IsNumericType(attrt) || Lookup() ? common::PackType::INT
: common::PackType::STR;
}
uint Precision() const { return precision; }
ushort Scale() const { return scale; }
uint CharLen() const { return precision / collation.collation->mbmaxlen; }
bool NotNull() const { return flag[static_cast<int>(enumATI::NOT_NULL)]; }
bool AutoInc() const { return flag[static_cast<int>(enumATI::AUTO_INC)]; }
void SetCollation(const DTCollation &collation) { this->collation = collation; }
void SetCollation(CHARSET_INFO *charset_info) { this->collation.set(charset_info); }
DTCollation GetCollation() const { return collation; }
CHARSET_INFO *CharsetInfo() const { return const_cast<CHARSET_INFO *>(this->collation.collation); }
const types::RCDataType &ValuePrototype() const;
common::PackFmt Fmt() const { return fmt; }
bool Lookup() const { return fmt == common::PackFmt::LOOKUP; }
unsigned char Flag() const { return flag.to_ulong(); }
void SetFlag(unsigned char v) { flag = std::bitset<std::numeric_limits<unsigned char>::digits>(v); }
private:
common::CT attrt;
common::PackFmt fmt;
uint precision;
int scale;
DTCollation collation;
std::bitset<std::numeric_limits<unsigned char>::digits> flag;
};
} // namespace core
} // namespace Tianmu
#endif // TIANMU_CORE_RC_ATTR_TYPEINFO_H_
此差异已折叠。
此差异已折叠。
/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved.
Use is subject to license terms
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-1335 USA
*/
#include "rc_data_types.h"
#include "core/rc_attr.h"
#include "core/rc_attr_typeinfo.h"
namespace Tianmu {
namespace types {
RCDataType::~RCDataType() {}
bool RCDataType::AreComperable(const RCDataType &rcdt) const { return RCDataType::AreComperable(*this, rcdt); }
bool RCDataType::AreComperable(const RCDataType &rcdt1, const RCDataType &rcdt2) {
common::CT att1 = rcdt1.Type();
common::CT att2 = rcdt2.Type();
return AreComparable(att1, att2);
}
bool RCDataType::compare(const RCDataType &rcdt1, const RCDataType &rcdt2, common::Operator op, char like_esc) {
// DEBUG_ASSERT(RCDataType::AreComperable(rcdt1, rcdt2));
if (op == common::Operator::O_LIKE || op == common::Operator::O_NOT_LIKE) {
if (rcdt1.IsNull() || rcdt2.IsNull())
return false;
BString x, y;
BString *rcbs1 = dynamic_cast<BString *>(const_cast<RCDataType *>(&rcdt1));
if (!rcbs1) {
x = rcdt1.ToBString();
rcbs1 = &x;
}
BString *rcbs2 = dynamic_cast<BString *>(const_cast<RCDataType *>(&rcdt2));
if (!rcbs2) {
y = rcdt2.ToBString();
rcbs2 = &y;
}
bool res = rcbs1->Like(*rcbs2, like_esc);
if (op == common::Operator::O_LIKE)
return res;
else
return !res;
} else if (!rcdt1.IsNull() && !rcdt2.IsNull() &&
(((op == common::Operator::O_EQ) && rcdt1 == rcdt2) ||
(op == common::Operator::O_NOT_EQ && rcdt1 != rcdt2) ||
(op == common::Operator::O_LESS && rcdt1 < rcdt2) ||
(op == common::Operator::O_LESS_EQ && (rcdt1 < rcdt2 || rcdt1 == rcdt2)) ||
(op == common::Operator::O_MORE && (!(rcdt1 < rcdt2) && rcdt1 != rcdt2)) ||
(op == common::Operator::O_MORE_EQ && (!(rcdt1 < rcdt2) || rcdt1 == rcdt2))))
return true;
return false;
}
bool RCDataType::compare(const RCDataType &rcdt, common::Operator op, char like_esc) const {
return RCDataType::compare(*this, rcdt, op, like_esc);
}
bool AreComparable(common::CT attr1_t, common::CT attr2_t) {
if (attr1_t == attr2_t)
return true;
if ((core::ATI::IsDateTimeType(attr1_t)) && (core::ATI::IsDateTimeType(attr2_t)))
return true;
if ((core::ATI::IsTxtType(attr2_t) && attr1_t == common::CT::VARBYTE) ||
(core::ATI::IsTxtType(attr1_t) && attr2_t == common::CT::VARBYTE))
return true;
if ((((attr1_t == common::CT::TIME) || (attr1_t == common::CT::DATE)) && attr2_t != common::CT::DATETIME) ||
(((attr2_t == common::CT::TIME) || (attr2_t == common::CT::DATE)) && attr1_t != common::CT::DATETIME) ||
(core::ATI::IsBinType(attr1_t) && !core::ATI::IsBinType(attr2_t)) ||
(core::ATI::IsBinType(attr2_t) && !core::ATI::IsBinType(attr1_t)) ||
(core::ATI::IsTxtType(attr1_t) && !core::ATI::IsTxtType(attr2_t)) ||
(core::ATI::IsTxtType(attr2_t) && !core::ATI::IsTxtType(attr1_t)))
return false;
return true;
}
bool RCDataType::ToDecimal(const RCDataType &in, int scale, RCNum &out) {
if (RCNum *rcn = dynamic_cast<RCNum *>(const_cast<RCDataType *>(&in))) {
if (rcn->IsDecimal(scale)) {
out = rcn->ToDecimal(scale);
return true;
}
} else if (BString *rcs = dynamic_cast<BString *>(const_cast<RCDataType *>(&in))) {
if (RCNum::Parse(*rcs, out) == common::ErrorCode::SUCCESS)
return true;
}
return false;
}
bool RCDataType::ToInt(const RCDataType &in, RCNum &out) {
if (RCNum *rcn = dynamic_cast<RCNum *>(const_cast<RCDataType *>(&in))) {
if (rcn->IsInt()) {
out = rcn->ToInt();
return true;
}
} else if (BString *rcs = dynamic_cast<BString *>(const_cast<RCDataType *>(&in))) {
if (RCNum::Parse(*rcs, out) == common::ErrorCode::SUCCESS)
return true;
}
return false;
}
bool RCDataType::ToReal(const RCDataType &in, RCNum &out) {
if (RCNum *rcn = dynamic_cast<RCNum *>(const_cast<RCDataType *>(&in))) {
if (rcn->IsReal()) {
out = rcn->ToReal();
return true;
}
} else if (BString *rcs = dynamic_cast<BString *>(const_cast<RCDataType *>(&in))) {
if (RCNum::ParseReal(*rcs, out, common::CT::UNK) == common::ErrorCode::SUCCESS)
return true;
}
return false;
}
ValueTypeEnum RCDataType::GetValueType(common::CT attr_type) {
if (core::ATI::IsNumericType(attr_type))
return ValueTypeEnum::NUMERIC_TYPE;
else if (core::ATI::IsDateTimeType(attr_type))
return ValueTypeEnum::DATE_TIME_TYPE;
else if (core::ATI::IsStringType(attr_type))
return ValueTypeEnum::STRING_TYPE;
return ValueTypeEnum::NULL_TYPE;
}
} // namespace types
} // namespace Tianmu
/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved.
Use is subject to license terms
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-1335 USA
*/
#include "rc_num.h"
#include <cmath>
#include "common/assert.h"
#include "core/tools.h"
#include "system/txt_utils.h"
#include "types/rc_data_types.h"
#include "types/value_parser4txt.h"
namespace Tianmu {
namespace types {
RCNum::RCNum(common::CT attrt) : value_(0), scale_(0), is_double_(false), is_dot_(false), attr_type_(attrt) {}
RCNum::RCNum(int64_t value_, short scale, bool is_double_, common::CT attrt) {
Assign(value_, scale, is_double_, attrt);
}
RCNum::RCNum(double value_)
: value_(*(int64_t *)&value_), scale_(0), is_double_(true), is_dot_(false), attr_type_(common::CT::REAL) {
null = (value_ == NULL_VALUE_D ? true : false);
}
RCNum::RCNum(const RCNum &rcn)
: ValueBasic<RCNum>(rcn),
value_(rcn.value_),
scale_(rcn.scale_),
is_double_(rcn.is_double_),
is_dot_(rcn.is_dot_),
attr_type_(rcn.attr_type_) {
null = rcn.null;
}
RCNum::~RCNum() {}
RCNum &RCNum::Assign(int64_t value_, short scale, bool is_double_, common::CT attrt) {
this->value_ = value_;
this->scale_ = scale;
this->is_double_ = is_double_;
this->attr_type_ = attrt;
if (scale != -1 && !is_double_) {
if (scale != 0 || attrt == common::CT::UNK) {
is_dot_ = true;
this->attr_type_ = common::CT::NUM;
}
}
if (scale <= -1 && !is_double_)
scale_ = 0;
if (is_double_) {
if (!(this->attr_type_ == common::CT::REAL || this->attr_type_ == common::CT::FLOAT))
this->attr_type_ = common::CT::REAL;
this->is_dot_ = false;
scale_ = 0;
null = (value_ == *(int64_t *)&NULL_VALUE_D ? true : false);
} else
null = (value_ == common::NULL_VALUE_64 ? true : false);
return *this;
}
RCNum &RCNum::Assign(double value_) {
this->value_ = *(int64_t *)&value_;
this->scale_ = 0;
this->is_double_ = true;
this->is_dot_ = false;
this->attr_type_ = common::CT::REAL;
common::double_int_t v(value_);
null = (v.i == common::NULL_VALUE_64 ? true : false);
return *this;
}
common::ErrorCode RCNum::Parse(const BString &rcs, RCNum &rcn, common::CT at) {
return ValueParserForText::Parse(rcs, rcn, at);
}
common::ErrorCode RCNum::ParseReal(const BString &rcbs, RCNum &rcn, common::CT at) {
return ValueParserForText::ParseReal(rcbs, rcn, at);
}
common::ErrorCode RCNum::ParseNum(const BString &rcs, RCNum &rcn, short scale) {
return ValueParserForText::ParseNum(rcs, rcn, scale);
}
RCNum &RCNum::operator=(const RCNum &rcn) {
value_ = rcn.value_;
is_double_ = rcn.is_double_;
scale_ = rcn.scale_;
null = rcn.null;
attr_type_ = rcn.attr_type_;
return *this;
}
RCNum &RCNum::operator=(const RCDataType &rcdt) {
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
*this = (RCNum &)rcdt;
else {
RCNum rcn1;
if (common::IsError(RCNum::Parse(rcdt.ToBString(), rcn1, this->attr_type_))) {
*this = rcn1;
} else {
TIANMU_ERROR("Unsupported assign operation!");
null = true;
}
}
return *this;
}
common::CT RCNum::Type() const { return attr_type_; }
bool RCNum::IsDecimal(ushort scale) const {
if (core::ATI::IsIntegerType(this->attr_type_)) {
return GetDecIntLen() <= (MAX_DEC_PRECISION - scale);
} else if (attr_type_ == common::CT::NUM) {
if (this->GetDecFractLen() <= scale)
return true;
if (scale_ > scale)
return value_ % (int64_t)Uint64PowOfTen(scale_ - scale) == 0;
return true;
} else {
double f = GetFractPart();
return f == 0.0 || (fabs(f) >= (1.0 / (double)Uint64PowOfTen(scale)));
}
return false;
}
bool RCNum::IsInt() const {
if (!is_double_) {
if ((value_ % (int64_t)Uint64PowOfTen(scale_)) != 0) {
return false;
}
return true;
}
return false;
}
RCNum RCNum::ToDecimal(int scale) const {
int64_t tmpv = 0;
short tmpp = 0;
int sign = 1;
if (is_double_) {
double intpart(0);
double fracpart(modf(*(double *)&value_, &intpart));
if (intpart < 0 || fracpart < 0) {
sign = -1;
intpart = fabs(intpart);
fracpart = fabs(fracpart);
}
if (scale == -1) {
if (intpart >= Uint64PowOfTen(MAX_DEC_PRECISION)) {
if (sign != 1)
scale = 0;
} else {
int l = 0;
if (intpart != 0)
l = (int)floor(log10(intpart)) + 1;
scale = MAX_DEC_PRECISION - l;
}
}
if (intpart >= Uint64PowOfTen(MAX_DEC_PRECISION)) {
tmpv = (Uint64PowOfTen(MAX_DEC_PRECISION) - 1);
} else
tmpv = (int64_t)intpart * Uint64PowOfTen(scale) + std::llround(fracpart * Uint64PowOfTen(scale));
tmpp = scale;
} else {
tmpv = this->value_;
tmpp = this->scale_;
if (scale != -1) {
if (tmpp > scale)
tmpv /= (int64_t)Uint64PowOfTen(tmpp - scale);
else
tmpv *= (int64_t)Uint64PowOfTen(scale - tmpp);
tmpp = scale;
}
}
return RCNum(tmpv * sign, tmpp);
}
RCNum RCNum::ToReal() const {
if (core::ATI::IsRealType(attr_type_)) {
return RCNum(*(double *)&value_);
}
return RCNum((double)((double)(this->value_ / PowOfTen(scale_))));
}
RCNum RCNum::ToInt() const { return GetIntPart(); }
static char *Text(int64_t value_, char buf[], int scale) {
bool sign = true;
if (value_ < 0) {
sign = false;
value_ *= -1;
}
longlong2str(value_, buf, 10);
int l = (int)std::strlen(buf);
std::memset(buf + l + 1, ' ', 21 - l);
int pos = 21;
int i = 0;
for (i = l; i >= 0; i--) {
if (scale != 0 && pos + scale == 20) {
buf[pos--] = '.';
i++;
} else {
buf[pos--] = buf[i];
buf[i] = ' ';
}
}
if (scale >= l) {
buf[20 - scale] = '.';
buf[20 - scale - 1] = '0';
i = 20 - scale + 1;
while (buf[i] == ' ') buf[i++] = '0';
}
pos = 0;
while (buf[pos] == ' ') pos++;
if (!sign)
buf[--pos] = '-';
return buf + pos;
}
BString RCNum::ToBString() const {
if (!IsNull()) {
static int const SIZE(24);
char buf[SIZE];
if (core::ATI::IsRealType(attr_type_)) {
gcvt(*(double *)&value_, 15, buf);
size_t s = std::strlen(buf);
if (s && buf[s - 1] == '.')
buf[s - 1] = 0;
} else if (core::ATI::IsIntegerType(attr_type_))
std::sprintf(buf, "%ld", value_);
else {
return BString(Text(value_, buf, scale_), 0, true);
}
return BString(buf, std::strlen(buf), true);
}
return BString();
}
RCNum::operator double() const {
return (core::ATI::IsRealType(Type()) || Type() == common::CT::FLOAT) ? *(double *)&value_
: GetIntPart() + GetFractPart();
}
bool RCNum::operator==(const RCDataType &rcdt) const {
if (null || rcdt.IsNull())
return false;
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
return (compare((RCNum &)rcdt) == 0);
if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return (compare((RCDateTime &)rcdt) == 0);
if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE)
return (rcdt == this->ToBString());
TIANMU_ERROR("Bad cast inside RCNum");
return false;
}
bool RCNum::operator!=(const RCDataType &rcdt) const {
if (null || rcdt.IsNull())
return false;
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
return (compare((RCNum &)rcdt) != 0);
if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return (compare((RCDateTime &)rcdt) != 0);
if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE)
return (rcdt != this->ToBString());
TIANMU_ERROR("Bad cast inside RCNum");
return false;
}
bool RCNum::operator<(const RCDataType &rcdt) const {
if (IsNull() || rcdt.IsNull())
return false;
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
return (compare((RCNum &)rcdt) < 0);
if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return (compare((RCDateTime &)rcdt) < 0);
if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE)
return (this->ToBString() < rcdt);
TIANMU_ERROR("Bad cast inside RCNum");
return false;
}
bool RCNum::operator>(const RCDataType &rcdt) const {
if (IsNull() || rcdt.IsNull())
return false;
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
return (compare((RCNum &)rcdt) > 0);
if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return (compare((RCDateTime &)rcdt) > 0);
if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE)
return (this->ToBString() > rcdt);
TIANMU_ERROR("Bad cast inside RCNum");
return false;
}
bool RCNum::operator<=(const RCDataType &rcdt) const {
if (IsNull() || rcdt.IsNull())
return false;
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
return (compare((RCNum &)rcdt) <= 0);
if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return (compare((RCDateTime &)rcdt) <= 0);
if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE)
return (this->ToBString() <= rcdt);
TIANMU_ERROR("Bad cast inside RCNum");
return false;
}
bool RCNum::operator>=(const RCDataType &rcdt) const {
if (null || rcdt.IsNull())
return false;
if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE)
return (compare((RCNum &)rcdt) >= 0);
if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return (compare((RCDateTime &)rcdt) >= 0);
if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE)
return (this->ToBString() >= rcdt);
TIANMU_ERROR("Bad cast inside RCNum");
return false;
}
RCNum &RCNum::operator-=(const RCNum &rcn) {
DEBUG_ASSERT(!null);
if (rcn.IsNull() || rcn.IsNull())
return *this;
if (IsReal() || rcn.IsReal()) {
if (IsReal() && rcn.IsReal())
*(double *)&value_ -= *(double *)&rcn.value_;
else {
if (IsReal())
*this -= rcn.ToReal();
else
*this -= rcn.ToDecimal();
}
} else {
if (scale_ < rcn.scale_) {
value_ = ((int64_t)(value_ * PowOfTen(rcn.scale_ - scale_)) - rcn.value_);
scale_ = rcn.scale_;
} else {
value_ -= (int64_t)(rcn.value_ * PowOfTen(scale_ - rcn.scale_));
}
}
return *this;
}
RCNum &RCNum::operator+=(const RCNum &rcn) {
DEBUG_ASSERT(!null);
if (rcn.IsNull() || rcn.IsNull())
return *this;
if (IsReal() || rcn.IsReal()) {
if (IsReal() && rcn.IsReal())
*(double *)&value_ -= *(double *)&rcn.value_;
else {
if (IsReal())
*this += rcn.ToReal();
else
*this += rcn.ToDecimal();
}
} else {
if (scale_ < rcn.scale_) {
value_ = ((int64_t)(value_ * PowOfTen(rcn.scale_ - scale_)) + rcn.value_);
scale_ = rcn.scale_;
} else {
value_ += (int64_t)(rcn.value_ * PowOfTen(scale_ - rcn.scale_));
}
}
return *this;
}
RCNum &RCNum::operator*=(const RCNum &rcn) {
DEBUG_ASSERT(!null);
if (rcn.IsNull() || rcn.IsNull())
return *this;
if (IsReal() || rcn.IsReal()) {
if (IsReal() && rcn.IsReal())
*(double *)&value_ -= *(double *)&rcn.value_;
else {
if (IsReal())
*this /= rcn.ToReal();
else
*this /= rcn.ToDecimal();
}
} else {
value_ *= rcn.value_;
scale_ += rcn.scale_;
}
return *this;
}
void fcvt(char *buf_, double val_, int digits_, int *dec_, int *sign_) {
static int const fmtlen = 10;
char format[fmtlen + 1];
std::snprintf(format, fmtlen + 1, "%%.%df", digits_);
std::snprintf(buf_, digits_, format, val_);
int len(std::strlen(buf_));
(*sign_) = (buf_[0] == '-') ? 1 : 0;
(*sign_) && std::memmove(buf_, buf_ + 1, len);
char *pbuf(buf_);
::strsep(&pbuf, ".,");
if (pbuf) {
(*dec_) = pbuf - buf_ - 1;
std::memmove(pbuf - 1, pbuf, std::strlen(pbuf) + 1);
}
return;
}
RCNum &RCNum::operator/=(const RCNum &rcn) {
DEBUG_ASSERT(!null);
if (rcn.IsNull() || rcn.IsNull())
return *this;
if (IsReal() || rcn.IsReal()) {
if (IsReal() && rcn.IsReal())
*(double *)&value_ -= *(double *)&rcn.value_;
else {
if (IsReal())
*this /= rcn.ToReal();
else
*this /= rcn.ToDecimal();
}
} else {
double tmv = ((double)(value_ / rcn.value_) / PowOfTen(scale_ - rcn.scale_));
int decimal = 0;
int sign;
static int const MAX_NUM_DIGITS = 21 + 1;
char buf[MAX_NUM_DIGITS - 1];
fcvt(buf, tmv, 18, &decimal, &sign);
buf[18] = 0;
ptrdiff_t lz = std::strlen(buf) - 1;
while (lz >= 0 && buf[lz--] == '0')
;
buf[lz + 2] = 0;
value_ = std::strtoll(buf, NULL, 10) * (sign == 1 ? -1 : 1);
scale_ = (short)((lz + 2) - decimal);
}
return *this;
}
RCNum RCNum::operator-(const RCNum &rcn) const {
RCNum res(*this);
return res -= rcn;
}
RCNum RCNum::operator+(const RCNum &rcn) const {
RCNum res(*this);
return res += rcn;
}
RCNum RCNum::operator*(const RCNum &rcn) const {
RCNum res(*this);
return res *= rcn;
}
RCNum RCNum::operator/(const RCNum &rcn) const {
RCNum res(*this);
return res /= rcn;
}
uint RCNum::GetHashCode() const { return uint(GetIntPart() * 1040021); }
int RCNum::compare(const RCNum &rcn) const {
if (IsNull() || rcn.IsNull())
return false;
if (IsReal() || rcn.IsReal()) {
if (IsReal() && rcn.IsReal())
return (*(double *)&value_ > *(double *)&rcn.value_ ? 1
: (*(double *)&value_ == *(double *)&rcn.value_ ? 0 : -1));
else {
if (IsReal())
return (*this > rcn.ToReal() ? 1 : (*this == rcn.ToReal() ? 0 : -1));
else
return (this->ToReal() > rcn ? 1 : (this->ToReal() == rcn ? 0 : -1));
}
} else {
if (scale_ != rcn.scale_) {
if (value_ < 0 && rcn.value_ >= 0)
return -1;
if (value_ >= 0 && rcn.value_ < 0)
return 1;
if (scale_ < rcn.scale_) {
int64_t power_of_ten = (int64_t)PowOfTen(rcn.scale_ - scale_);
int64_t tmpv = (int64_t)(rcn.value_ / power_of_ten);
if (value_ > tmpv)
return 1;
if (value_ < tmpv || rcn.value_ % power_of_ten > 0)
return -1;
if (rcn.value_ % power_of_ten < 0)
return 1;
return 0;
} else {
int64_t power_of_ten = (int64_t)PowOfTen(scale_ - rcn.scale_);
int64_t tmpv = (int64_t)(value_ / power_of_ten);
if (tmpv < rcn.value_)
return -1;
if (tmpv > rcn.value_ || value_ % power_of_ten > 0)
return 1;
if (value_ % power_of_ten < 0)
return -1;
return 0;
}
} else
return (value_ > rcn.value_ ? 1 : (value_ == rcn.value_ ? 0 : -1));
}
}
int RCNum::compare(const RCDateTime &rcdt) const {
int64_t tmp;
rcdt.ToInt64(tmp);
return int(GetIntPart() - tmp);
}
double RCNum::GetIntPartAsDouble() const {
if (is_double_) {
double integer;
modf(*(double *)&value_, &integer);
return integer;
} else {
return (double)(value_ / (int64_t)Uint64PowOfTen(scale_));
}
}
double RCNum::GetFractPart() const {
if (is_double_) {
double fract, integer;
fract = modf(*(double *)&value_, &integer);
return fract;
} else {
double tmpv = ((double)value_ / Uint64PowOfTen(scale_));
double fract, integer;
fract = modf(tmpv, &integer);
return fract;
}
}
short RCNum::GetDecStrLen() const {
if (IsNull())
return 0;
if (is_double_)
return 18;
short res = scale_;
int64_t tmpi = value_ / (int64_t)PowOfTen(scale_);
while (tmpi != 0) {
tmpi /= 10;
res++;
}
return res;
}
short RCNum::GetDecIntLen() const {
if (IsNull())
return 0;
short res = 0;
int64_t tmpi = 0;
if (is_double_)
tmpi = GetIntPart();
else {
tmpi = value_ / (int64_t)PowOfTen(scale_);
}
while (tmpi != 0) {
tmpi /= 10;
res++;
}
return res;
}
short RCNum::GetDecFractLen() const {
if (IsNull())
return 0;
return scale_;
}
void RCNum::Negate() {
if (IsNull())
return;
if (is_double_)
*(double *)&value_ = *(double *)&value_ * -1;
else
value_ *= -1;
}
} // namespace types
} // namespace Tianmu
/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved.
Use is subject to license terms
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-1335 USA
*/
#ifndef TIANMU_TYPES_RC_NUM_H_
#define TIANMU_TYPES_RC_NUM_H_
#pragma once
#include "types/rc_data_types.h"
namespace Tianmu {
namespace types {
class BString;
class RCNum : public ValueBasic<RCNum> {
friend class ValueParserForText;
friend class Engine;
public:
RCNum(common::CT attrt = common::CT::NUM);
RCNum(int64_t value, short scale = -1, bool dbl = false, common::CT attrt = common::CT::UNK);
RCNum(double value);
RCNum(const RCNum &);
~RCNum();
RCNum &Assign(int64_t value, short scale = -1, bool dbl = false, common::CT attrt = common::CT::UNK);
RCNum &Assign(double value);
static common::ErrorCode Parse(const BString &rcs, RCNum &rcn, common::CT at = common::CT::UNK);
static common::ErrorCode ParseReal(const BString &, RCNum &, common::CT at);
static common::ErrorCode ParseNum(const BString &, RCNum &, short scale = -1);
RCNum &operator=(const RCNum &rcn);
RCNum &operator=(const RCDataType &rcdt) override;
common::CT Type() const override;
bool operator==(const RCDataType &rcdt) const override;
bool operator<(const RCDataType &rcdt) const override;
bool operator>(const RCDataType &rcdt) const override;
bool operator>=(const RCDataType &rcdt) const override;
bool operator<=(const RCDataType &rcdt) const override;
bool operator!=(const RCDataType &rcdt) const override;
RCNum &operator-=(const RCNum &rcn);
RCNum &operator+=(const RCNum &rcn);
RCNum &operator*=(const RCNum &rcn);
RCNum &operator/=(const RCNum &rcn);
RCNum operator-(const RCNum &rcn) const;
RCNum operator+(const RCNum &rcn) const;
RCNum operator*(const RCNum &rcn) const;
RCNum operator/(const RCNum &rcn) const;
bool IsDecimal(ushort scale) const;
bool IsReal() const { return is_double_; }
bool IsInt() const;
BString ToBString() const override;
RCNum ToDecimal(int scale = -1) const;
RCNum ToReal() const;
RCNum ToInt() const;
operator int64_t() const { return GetIntPart(); }
operator double() const;
operator float() const { return (float)(double)*this; }
short Scale() const { return scale_; }
int64_t ValueInt() const { return value_; }
char *GetDataBytesPointer() const override { return (char *)&value_; }
int64_t GetIntPart() const {
return is_double_ ? (int64_t)GetIntPartAsDouble() : value_ / (int64_t)Uint64PowOfTen(scale_);
}
int64_t GetValueInt64() const { return value_; }
double GetIntPartAsDouble() const;
double GetFractPart() const;
short GetDecStrLen() const;
short GetDecIntLen() const;
short GetDecFractLen() const;
uint GetHashCode() const override;
void Negate();
private:
int compare(const RCNum &rcn) const;
int compare(const RCDateTime &rcn) const;
private:
static constexpr int MAX_DEC_PRECISION = 18;
int64_t value_;
ushort scale_; // means 'scale' actually
bool is_double_;
bool is_dot_;
common::CT attr_type_;
public:
const static ValueTypeEnum value_type = ValueTypeEnum::NUMERIC_TYPE;
};
} // namespace types
} // namespace Tianmu
#endif // TIANMU_TYPES_RC_NUM_H_
/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved.
Use is subject to license terms
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-1335 USA
*/
#include "types/rc_num.h"
namespace Tianmu {
namespace types {
RCValueObject::RCValueObject() {}
RCValueObject::RCValueObject(const RCValueObject &rcvo) {
if (rcvo.value.get())
construct(*rcvo.value);
}
RCValueObject::RCValueObject(const RCDataType &rcdt) { construct(rcdt); }
RCValueObject::~RCValueObject() {}
RCValueObject &RCValueObject::operator=(const RCValueObject &rcvo) {
if (rcvo.value.get())
construct(*rcvo.value);
else
value.reset();
return *this;
}
inline void RCValueObject::construct(const RCDataType &rcdt) { value = rcdt.Clone(); }
bool RCValueObject::compare(const RCValueObject &rcvo1, const RCValueObject &rcvo2, common::Operator op,
char like_esc) {
if (rcvo1.IsNull() || rcvo2.IsNull())
return false;
else
return RCDataType::compare(*rcvo1.value, *rcvo2.value, op, like_esc);
}
bool RCValueObject::compare(const RCValueObject &rcvo, common::Operator op, char like_esc) const {
return compare(*this, rcvo, op, like_esc);
}
bool RCValueObject::operator==(const RCValueObject &rcvo) const {
if (IsNull() || rcvo.IsNull())
return false;
return *value == *rcvo.value;
}
bool RCValueObject::operator<(const RCValueObject &rcvo) const {
if (IsNull() || rcvo.IsNull())
return false;
return *value < *rcvo.value;
}
bool RCValueObject::operator>(const RCValueObject &rcvo) const {
if (IsNull() || rcvo.IsNull())
return false;
return *value > *rcvo.value;
}
bool RCValueObject::operator>=(const RCValueObject &rcvo) const {
if (IsNull() || rcvo.IsNull())
return false;
return *value >= *rcvo.value;
}
bool RCValueObject::operator<=(const RCValueObject &rcvo) const {
if (IsNull() || rcvo.IsNull())
return false;
return *value <= *rcvo.value;
}
bool RCValueObject::operator!=(const RCValueObject &rcvo) const {
if (IsNull() || rcvo.IsNull())
return false;
return *value != *rcvo.value;
}
bool RCValueObject::operator==(const RCDataType &rcn) const {
if (IsNull() || rcn.IsNull())
return false;
return *value == rcn;
}
bool RCValueObject::operator<(const RCDataType &rcn) const {
if (IsNull() || rcn.IsNull())
return false;
return *value < rcn;
}
bool RCValueObject::operator>(const RCDataType &rcn) const {
if (IsNull() || rcn.IsNull())
return false;
return *value > rcn;
}
bool RCValueObject::operator>=(const RCDataType &rcn) const {
if (IsNull() || rcn.IsNull())
return false;
return *value >= rcn;
}
bool RCValueObject::operator<=(const RCDataType &rcdt) const {
if (IsNull() || rcdt.IsNull())
return false;
return *value <= rcdt;
}
bool RCValueObject::operator!=(const RCDataType &rcn) const {
if (IsNull() || rcn.IsNull())
return false;
return *value != rcn;
}
bool RCValueObject::IsNull() const { return value.get() ? value->IsNull() : true; }
RCDataType &RCValueObject::operator*() const { return value.get() ? *value.get() : RCNum::NullValue(); }
RCValueObject::operator RCNum &() const {
if (IsNull())
return RCNum::NullValue();
if (GetValueType() == ValueTypeEnum::NUMERIC_TYPE || GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return static_cast<RCNum &>(*value);
TIANMU_ERROR("Bad cast in RCValueObject::RCNum&()");
return static_cast<RCNum &>(*value);
}
RCValueObject::operator RCDateTime &() const {
if (IsNull())
return RCDateTime::NullValue();
if (GetValueType() == ValueTypeEnum::DATE_TIME_TYPE)
return static_cast<RCDateTime &>(*value);
TIANMU_ERROR("Bad cast in RCValueObject::RCDateTime&()");
return static_cast<RCDateTime &>(*value);
}
BString RCValueObject::ToBString() const {
if (IsNull())
return BString();
return value->ToBString();
}
uint RCValueObject::GetHashCode() const {
if (IsNull())
return 0;
return value->GetHashCode();
}
} // namespace types
} // namespace Tianmu
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册