Skip to content

Commit

Permalink
fix(tianmu): support add integer/decimal column DDL with default valu…
Browse files Browse the repository at this point in the history
…e. (stoneatom#1187)

[summary]
check the default value of field,please see tianmu_attr.cpp for details:
1. if field is integer type but not real type;
2. if field is integer type and also real type;
3. if field is not integer type;
  • Loading branch information
lujiashun committed Jan 11, 2023
1 parent 3fa2aab commit 5d681ba
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 79 deletions.
45 changes: 45 additions & 0 deletions mysql-test/suite/tianmu/r/issue1187.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
DROP DATABASE IF EXISTS issuse1187_test;
CREATE DATABASE issuse1187_test;
create table t1(id int,name varchar(5)) ;
insert into t1 values(1,'AAA'),(2,'BBB');
alter table t1 add column age int null;
select * from t1;
id name age
1 AAA NULL
2 BBB NULL
create table t2(id int,name varchar(5)) ;
insert into t2 values(1,'AAA'),(2,'BBB');
alter table t2 add column age int not null;
select * from t2;
id name age
1 AAA 0
2 BBB 0
create table t3(id int,name varchar(5)) ;
insert into t3 values(1,'AAA'),(2,'BBB');
alter table t3 add column age int not null default 66;
select * from t3;
id name age
1 AAA 66
2 BBB 66
create table t4(id int,name varchar(5)) ;
insert into t4 values(1,'AAA'),(2,'BBB');
alter table t4 add column age DECIMAL(17,9);
select * from t4;
id name age
1 AAA NULL
2 BBB NULL
create table t5(id int,name varchar(5)) ;
insert into t5 values(1,'AAA'),(2,'BBB');
alter table t5 add column age DECIMAL(17,9) not null;
select * from t5;
id name age
1 AAA 0.000000000
2 BBB 0.000000000
create table t6(id int,name varchar(5)) ;
insert into t6 values(1,'AAA'),(2,'BBB');
alter table t6 add column age DECIMAL(17,9) not null default '800.0024';
select * from t6;
id name age
1 AAA 800.002400000
2 BBB 800.002400000
DROP DATABASE issuse1187_test;
39 changes: 39 additions & 0 deletions mysql-test/suite/tianmu/t/issue1187.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--source include/have_tianmu.inc

--disable_warnings
DROP DATABASE IF EXISTS issuse1187_test;
--enable_warnings

CREATE DATABASE issuse1187_test;

create table t1(id int,name varchar(5)) ;
insert into t1 values(1,'AAA'),(2,'BBB');
alter table t1 add column age int null;
select * from t1;

create table t2(id int,name varchar(5)) ;
insert into t2 values(1,'AAA'),(2,'BBB');
alter table t2 add column age int not null;
select * from t2;

create table t3(id int,name varchar(5)) ;
insert into t3 values(1,'AAA'),(2,'BBB');
alter table t3 add column age int not null default 66;
select * from t3;

create table t4(id int,name varchar(5)) ;
insert into t4 values(1,'AAA'),(2,'BBB');
alter table t4 add column age DECIMAL(17,9);
select * from t4;

create table t5(id int,name varchar(5)) ;
insert into t5 values(1,'AAA'),(2,'BBB');
alter table t5 add column age DECIMAL(17,9) not null;
select * from t5;

create table t6(id int,name varchar(5)) ;
insert into t6 values(1,'AAA'),(2,'BBB');
alter table t6 add column age DECIMAL(17,9) not null default '800.0024';
select * from t6;

DROP DATABASE issuse1187_test;
10 changes: 9 additions & 1 deletion storage/tianmu/core/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,15 @@ std::shared_ptr<TableOption> Engine::GetTableOption(const std::string &table, TA

void Engine::CreateTable(const std::string &table, TABLE *form) { TianmuTable::CreateNew(GetTableOption(table, form)); }

AttributeTypeInfo Engine::GetAttrTypeInfo(const Field &field) {
AttributeTypeInfo Engine::GetAttrTypeInfo(Field &field) {
AttributeTypeInfo ati = GetAttrTypeInfoInternal(field);
bitmap_set_bit(field.table->write_set, field.field_index);
bitmap_set_bit(field.table->read_set, field.field_index);
field.set_default();
ati.SetDefaultValue(&field);
return ati;
}
AttributeTypeInfo Engine::GetAttrTypeInfoInternal(const Field &field) {
bool auto_inc = field.flags & AUTO_INCREMENT_FLAG;
if (auto_inc && field.part_of_key.to_ulonglong() == 0) {
throw common::AutoIncException("AUTO_INCREMENT can be only declared on primary key column!");
Expand Down
4 changes: 3 additions & 1 deletion storage/tianmu/core/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ class Engine final {
public:
static common::ColumnType GetCorrespondingType(const Field &field);
static AttributeTypeInfo GetCorrespondingATI(Field &field);
static AttributeTypeInfo GetAttrTypeInfo(const Field &field);
static AttributeTypeInfo GetCorrespondingATIInternal(Field &field);
static AttributeTypeInfo GetAttrTypeInfo(Field &field);
static AttributeTypeInfo GetAttrTypeInfoInternal(const Field &field);
static common::ColumnType GetCorrespondingType(const enum_field_types &eft);
static bool IsTianmuTable(TABLE *table);
static bool ConvertToField(Field *field, types::TianmuDataType &tianmu_item, std::vector<uchar> *blob_buf);
Expand Down
4 changes: 4 additions & 0 deletions storage/tianmu/core/engine_convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ common::ColumnType Engine::GetCorrespondingType(const Field &field) {
}

AttributeTypeInfo Engine::GetCorrespondingATI(Field &field) {
AttributeTypeInfo ati = GetCorrespondingATIInternal(field);
return ati;
}
AttributeTypeInfo Engine::GetCorrespondingATIInternal(Field &field) {
common::ColumnType at = GetCorrespondingType(field);

if (ATI::IsNumericType(at)) {
Expand Down
78 changes: 64 additions & 14 deletions storage/tianmu/core/tianmu_attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,42 @@ void TianmuAttr::Create(const fs::path &dir, const AttributeTypeInfo &ati, uint8
fmeta.WriteExact(&meta, sizeof(meta));
fmeta.Flush();

size_t no_nulls{no_rows};
int64_t min{0};
int64_t max{0};
bool int_not_null{false};
bool is_real{false};
core::Value value = ati.GetDefaultValue();
if (ati.GetPackType() == common::PackType::INT && value.HasValue()) {
int_not_null = true;
}
if (ATI::IsRealType(ati.Type())) {
is_real = true;
}

if (int_not_null) {
no_nulls = 0;
if (is_real) {
common::double_int_t t(value.GetDouble());
min = max = t.i;
} else {
min = max = value.GetInt();
}
}

COL_VER_HDR hdr{
no_rows, // no_obj
no_rows, // no_nulls
no_pack, // no of packs
0, // no of deleted
0, // auto_inc next
0, // min
0, // max
0, // dict file version name. 0 means n/a
0, // is unique?
0, // is unique_updated?
0, // natural size
0, // compressed size
no_rows, // no_obj
no_nulls, // no_nulls
no_pack, // no of packs
0, // no of deleted
0, // auto_inc next
min, // min
max, // max
0, // dict file version name. 0 means n/a
0, // is unique?
0, // is unique_updated?
0, // natural size
0, // compressed size
};

if (ati.Lookup()) {
Expand Down Expand Up @@ -128,7 +151,20 @@ void TianmuAttr::Create(const fs::path &dir, const AttributeTypeInfo &ati, uint8
DPN dpn;
dpn.reset();
dpn.used = 1;
dpn.numOfNulls = 1 << pss;
if (int_not_null) {
dpn.numOfNulls = 0;
if (is_real) {
dpn.max_d = value.GetDouble();
dpn.min_d = value.GetDouble();
dpn.sum_d = value.GetDouble() * (1 << pss);
} else {
dpn.max_i = value.GetInt();
dpn.min_i = value.GetInt();
dpn.sum_i = value.GetInt() * (1 << pss);
}
} else {
dpn.numOfNulls = 1 << pss;
}
dpn.numOfRecords = 1 << pss;
dpn.xmax = common::MAX_XID;
dpn.dataAddress = DPN_INVALID_ADDR;
Expand All @@ -141,7 +177,21 @@ void TianmuAttr::Create(const fs::path &dir, const AttributeTypeInfo &ati, uint8
auto left = no_rows % (1 << pss);
if (left != 0) {
dpn.numOfRecords = left;
dpn.numOfNulls = left;

if (int_not_null) {
dpn.numOfNulls = 0;
if (is_real) {
dpn.max_d = value.GetDouble();
dpn.min_d = value.GetDouble();
dpn.sum_d = value.GetDouble() * left;
} else {
dpn.max_i = value.GetInt();
dpn.min_i = value.GetInt();
dpn.sum_i = value.GetInt() * left;
}
} else {
dpn.numOfNulls = left;
}
}
fdn.WriteExact(&dpn, sizeof(dpn));
fdn.Flush();
Expand Down
4 changes: 4 additions & 0 deletions storage/tianmu/core/tianmu_attr_typeinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "common/data_format.h"
#include "common/txt_data_format.h"
#include "core/tianmu_attr.h"
#include "handler/ha_tianmu.h"
#include "types/tianmu_data_types.h"
#include "types/tianmu_num.h"

Expand All @@ -36,5 +37,8 @@ const types::TianmuDataType &AttributeTypeInfo::ValuePrototype() const {
DEBUG_ASSERT(ATI::IsDateTimeType(attrt_));
return types::TianmuDateTime::NullValue();
}

void AttributeTypeInfo::SetDefaultValue(Field *field) { value_ = Tianmu::handler::GetValueFromField(field); }

} // namespace core
} // namespace Tianmu
4 changes: 4 additions & 0 deletions storage/tianmu/core/tianmu_attr_typeinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <bitset>

#include "common/common_definitions.h"
#include "value.h"

namespace Tianmu {
namespace types {
Expand Down Expand Up @@ -124,6 +125,8 @@ class AttributeTypeInfo {
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); }
void SetDefaultValue(Field *field);
core::Value GetDefaultValue() const { return value_; }

private:
common::ColumnType attrt_;
Expand All @@ -132,6 +135,7 @@ class AttributeTypeInfo {
int scale_;
DTCollation collation_;
std::string field_name_;
core::Value value_;

std::bitset<std::numeric_limits<unsigned char>::digits> flag_;
};
Expand Down
125 changes: 65 additions & 60 deletions storage/tianmu/core/value.h
Original file line number Diff line number Diff line change
@@ -1,60 +1,65 @@
/* 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_VALUE_H_
#define TIANMU_CORE_VALUE_H_
#pragma once

#include <string>
#include <variant>

namespace Tianmu {
namespace core {
class Value final {
public:
Value() = default;
explicit Value(int64_t i) { var = i; }
~Value() = default;

bool HasValue() const { return !std::holds_alternative<std::monostate>(var); }
bool IsInt() const { return std::holds_alternative<int64_t>(var); }
bool IsDouble() const { return std::holds_alternative<double>(var); }
bool IsString() const { return std::holds_alternative<std::string>(var); }
bool IsStringView() const { return std::holds_alternative<std::string_view>(var); }

void SetInt(int64_t v) { var = v; }
int64_t &GetInt() { return std::get<int64_t>(var); }
const int64_t &GetInt() const { return std::get<int64_t>(var); }

void SetDouble(double v) { var = v; }
double &GetDouble() { return std::get<double>(var); }
const double &GetDouble() const { return std::get<double>(var); }

void SetString(char *s, uint n) { var.emplace<std::string>(s, n); }
std::string &GetString() { return std::get<std::string>(var); }
const std::string &GetString() const { return std::get<std::string>(var); }

void SetStringView(char *s, uint n) { var.emplace<std::string_view>(s, n); }
std::string_view &GetStringView() { return std::get<std::string_view>(var); }
const std::string_view &GetStringView() const { return std::get<std::string_view>(var); }

private:
std::variant<std::monostate, int64_t, double, std::string, std::string_view> var;
};
} // namespace core
} // namespace Tianmu

#endif // TIANMU_CORE_VALUE_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
*/
#ifndef TIANMU_CORE_VALUE_H_
#define TIANMU_CORE_VALUE_H_
#pragma once

#include <string>
#include <variant>

namespace Tianmu {
namespace core {
class Value final {
public:
Value() = default;
Value(const Value &v) {
if (this != &v)
*this = v;
}
Value &operator=(const Value &) = default;
explicit Value(int64_t i) { var = i; }
~Value() = default;

bool HasValue() const { return !std::holds_alternative<std::monostate>(var); }
bool IsInt() const { return std::holds_alternative<int64_t>(var); }
bool IsDouble() const { return std::holds_alternative<double>(var); }
bool IsString() const { return std::holds_alternative<std::string>(var); }
bool IsStringView() const { return std::holds_alternative<std::string_view>(var); }

void SetInt(int64_t v) { var = v; }
int64_t &GetInt() { return std::get<int64_t>(var); }
const int64_t &GetInt() const { return std::get<int64_t>(var); }

void SetDouble(double v) { var = v; }
double &GetDouble() { return std::get<double>(var); }
const double &GetDouble() const { return std::get<double>(var); }

void SetString(char *s, uint n) { var.emplace<std::string>(s, n); }
std::string &GetString() { return std::get<std::string>(var); }
const std::string &GetString() const { return std::get<std::string>(var); }

void SetStringView(char *s, uint n) { var.emplace<std::string_view>(s, n); }
std::string_view &GetStringView() { return std::get<std::string_view>(var); }
const std::string_view &GetStringView() const { return std::get<std::string_view>(var); }

private:
std::variant<std::monostate, int64_t, double, std::string, std::string_view> var;
};
} // namespace core
} // namespace Tianmu

#endif // TIANMU_CORE_VALUE_H_
Loading

0 comments on commit 5d681ba

Please sign in to comment.