mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-04-23 07:05:36 +03:00
Remove redundant cast. As C-style casts with a type name in parantheses are interpreted as static_casts this literally just changes the interpretation around (and forces an implicit cast to match the return value of the function). Switch UBIGINTNULL and UBIGINTEMPTYROW constants for consistency. Make consistent with relation between BIGINTNULL and BIGINTEMPTYROW & make adapted cast behaviour due to NULL markers more intuitive. (After this change we can simply block the highest possible uint64_t value and if a cast results in it, print the next lower value (2^64 - 2). Previously, (2^64 - 1) was able to be printed, but (2^64 - 2) as being blocked by the UBIGINTNULL constant was not, making finding the appropiate replacement value to give out more confusing. Introduce MAX_MCS_UBIGINT and MIN_MCS_BIGINT and adapt casts. Adapt casting to BIGINT to remove NULL marker error. Add bugfix regression test for MCOL 4632 Add regression test for mcol_4648 Revert "Switch UBIGINTNULL and UBIGINTEMPTYROW constants for consistency." This reverts commit 83eac11b18937ecb0b4c754dd48e4cb47310f620. Due to backwards compatability issues. Refactor casting to MCS[U]Int to datatype functions. Update regression tests to include other affected datatypes. Apply formatting. Refactor according to PR review Remove redundant new constant, switch to using already existing constant. Adapt nullstring casting to EMPTYROW markers for backwards compatability. Adapt tests for backward compatability behaviour allowing text datatypes to be casted to EMPTYROW constant. Adapt mcol641-functions test according to bug fix. Update tests according to new expected behaviour. Adapt tests to new understanding of issue. Update comments/documentation for MCOL_4632 test. Adapt to new cast limit logic. Make bracketing consistent. Adapt previous regression test to new expected behaviour.
242 lines
5.6 KiB
C++
242 lines
5.6 KiB
C++
/* Copyright (C) 2022, 2023 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. */
|
|
|
|
// nullstring.h
|
|
//
|
|
// A class that can reprpesent string-with-NULL (special value not representable by a string value).
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include "exceptclasses.h"
|
|
#include "conststring.h"
|
|
#include "mcs_datatype_basic.h"
|
|
|
|
namespace utils
|
|
{
|
|
// A class for striings that can hold NULL values - a value that is separate from all possible string.
|
|
class NullString
|
|
{
|
|
protected:
|
|
std::shared_ptr<std::string> mStrPtr;
|
|
|
|
public:
|
|
NullString() : mStrPtr(nullptr)
|
|
{
|
|
}
|
|
NullString(const char* str, size_t length)
|
|
{
|
|
idbassert(str != nullptr || length == 0);
|
|
|
|
if (str)
|
|
{
|
|
mStrPtr.reset(new std::string((const char*)str, length));
|
|
}
|
|
}
|
|
// XXX: this constructor is used to construct NullString from char*. Please be
|
|
// aware of that - std::string(nullptr) throws exception and you should check
|
|
// for nullptr.
|
|
explicit NullString(const std::string& str) : mStrPtr(new std::string(str))
|
|
{
|
|
}
|
|
explicit NullString(const ConstString& str) : mStrPtr()
|
|
{
|
|
assign((const uint8_t*)str.str(), str.length());
|
|
}
|
|
ConstString toConstString() const
|
|
{
|
|
if (isNull())
|
|
{
|
|
return ConstString(nullptr, 0);
|
|
}
|
|
return ConstString(mStrPtr->c_str(), mStrPtr->length());
|
|
}
|
|
uint64_t toMCSUInt64() const
|
|
{
|
|
if (isNull())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
const uint64_t val = static_cast<uint64_t>(strtoul(str(), 0, 0));
|
|
//@Bug 4632 and 4648: Don't return marker value for NULL, but allow return of marker value for EMPTYROW.
|
|
return val == joblist::UBIGINTNULL ? MAX_UBIGINT : val;
|
|
}
|
|
int64_t toMCSInt64() const
|
|
{
|
|
if (isNull())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
const int64_t val = static_cast<int64_t>(atoll(str()));
|
|
//@Bug 4632 and 4648: Don't return marker value for NULL, but allow return of marker value for EMPTYROW.
|
|
return std::max(val, static_cast<int64_t>(joblist::BIGINTEMPTYROW));
|
|
}
|
|
const char* str() const
|
|
{
|
|
if (!mStrPtr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
return mStrPtr->c_str();
|
|
}
|
|
const char* end() const
|
|
{
|
|
if (!mStrPtr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
return str() + length();
|
|
}
|
|
size_t length() const
|
|
{
|
|
if (!mStrPtr)
|
|
{
|
|
return 0;
|
|
}
|
|
return mStrPtr->length();
|
|
}
|
|
std::string toString() const
|
|
{
|
|
idbassert(mStrPtr);
|
|
return std::string(*mStrPtr);
|
|
}
|
|
// "unsafe" means we do not check for NULL.
|
|
// it should be used after we know there is data in NullString.
|
|
const std::string& unsafeStringRef() const
|
|
{
|
|
idbassert(mStrPtr);
|
|
return (*mStrPtr);
|
|
}
|
|
bool eq(char ch) const
|
|
{
|
|
return length() == 1 && str()[0] == ch;
|
|
}
|
|
// this is SQL-like NULL handling equality. NULL will not be equal to anything, including NULL.
|
|
bool eq(const NullString& rhs) const
|
|
{
|
|
if (!rhs.mStrPtr)
|
|
{
|
|
return false;
|
|
}
|
|
if (!mStrPtr)
|
|
{
|
|
return false;
|
|
}
|
|
return *mStrPtr == *(rhs.mStrPtr);
|
|
}
|
|
NullString& rtrimZero()
|
|
{
|
|
return *this; // TODO
|
|
}
|
|
// this can be used to safely get a string value, with default value for NULL substitution.
|
|
// it does not raise anything and provides some nonsensical default value for you that will be
|
|
// easy to find.
|
|
std::string safeString(const char* defaultValue = "<<<no default value for null provided>>>") const
|
|
{
|
|
if (!mStrPtr)
|
|
{
|
|
return std::string(defaultValue);
|
|
}
|
|
return std::string(*mStrPtr);
|
|
}
|
|
bool isNull() const
|
|
{
|
|
return !mStrPtr;
|
|
}
|
|
void resize(size_t newSize, char pad)
|
|
{
|
|
if (mStrPtr)
|
|
{
|
|
mStrPtr->resize(newSize, pad);
|
|
}
|
|
}
|
|
NullString& dropString()
|
|
{
|
|
mStrPtr.reset();
|
|
return (*this);
|
|
}
|
|
void assign(const uint8_t* p, size_t len)
|
|
{
|
|
if (!p)
|
|
{
|
|
mStrPtr.reset();
|
|
return;
|
|
}
|
|
mStrPtr.reset(new std::string((const char*)p, len));
|
|
}
|
|
void assign(const std::string& newVal)
|
|
{
|
|
mStrPtr.reset(new std::string(newVal));
|
|
}
|
|
// XXX: here we implement what Row::equals expects.
|
|
// It is not SQL-NULL-handling compatible, please beware.
|
|
bool operator==(const NullString& a) const
|
|
{
|
|
if (!mStrPtr && !a.mStrPtr)
|
|
{
|
|
return true;
|
|
}
|
|
if (!mStrPtr)
|
|
{
|
|
return false;
|
|
}
|
|
if (!a.mStrPtr)
|
|
{
|
|
return false;
|
|
}
|
|
// fall to std::string equality.
|
|
return (*mStrPtr) == (*a.mStrPtr);
|
|
}
|
|
bool operator==(const std::string& a) const
|
|
{
|
|
if (!mStrPtr)
|
|
{
|
|
return false;
|
|
}
|
|
// fall to std::string equality.
|
|
return (*mStrPtr) == a;
|
|
}
|
|
bool operator<(const NullString& a) const
|
|
{
|
|
// order NULLs first.
|
|
if (isNull() > a.isNull())
|
|
{
|
|
return true;
|
|
}
|
|
if (isNull() < a.isNull())
|
|
{
|
|
return false;
|
|
}
|
|
if (!isNull())
|
|
{
|
|
// fall to std::string equality.
|
|
return (*mStrPtr) < (*a.mStrPtr);
|
|
}
|
|
return false; // both are NULLs.
|
|
}
|
|
bool operator>(const NullString& a) const
|
|
{
|
|
return a < (*this);
|
|
}
|
|
};
|
|
|
|
} // namespace utils.
|