Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions extension/icu/icu-datefunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,34 @@ ICUDateFunc::BindData::BindData(const BindData &other)
: tz_setting(other.tz_setting), cal_setting(other.cal_setting), calendar(other.calendar->clone()) {
}

ICUDateFunc::BindData::BindData(const string &tz_setting_p, const string &cal_setting_p)
: tz_setting(tz_setting_p), cal_setting(cal_setting_p) {

InitCalendar();
}

ICUDateFunc::BindData::BindData(ClientContext &context) {
Value tz_value;
if (context.TryGetCurrentSetting("TimeZone", tz_value)) {
tz_setting = tz_value.ToString();
}
auto tz = icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(icu::StringPiece(tz_setting)));

string cal_id("@calendar=");
Value cal_value;
if (context.TryGetCurrentSetting("Calendar", cal_value)) {
cal_setting = cal_value.ToString();
cal_id += cal_setting;
} else {
cal_id += "gregorian";
cal_setting = "gregorian";
}

InitCalendar();
}

void ICUDateFunc::BindData::InitCalendar() {
auto tz = icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(icu::StringPiece(tz_setting)));

string cal_id("@calendar=");
cal_id += cal_setting;

icu::Locale locale(cal_id.c_str());

UErrorCode success = U_ZERO_ERROR;
Expand Down
58 changes: 39 additions & 19 deletions extension/icu/icu-datepart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,13 @@ struct ICUDatePart : public ICUDateFunc {
using bigints_t = vector<part_bigint_t>;
using doubles_t = vector<part_double_t>;

BindStructData(ClientContext &context, part_codes_t &part_codes_p, bigints_t &bigints_p, doubles_t &doubles_p)
: BindData(context), part_codes(part_codes_p), bigints(bigints_p), doubles(doubles_p) {
BindStructData(ClientContext &context, part_codes_t &&part_codes_p)
: BindData(context), part_codes(part_codes_p) {
InitFactories();
}
BindStructData(const string &tz_setting_p, const string &cal_setting_p, part_codes_t &&part_codes_p)
: BindData(tz_setting_p, cal_setting_p), part_codes(part_codes_p) {
InitFactories();
}
BindStructData(const BindStructData &other)
: BindData(other), part_codes(other.part_codes), bigints(other.bigints), doubles(other.doubles) {
Expand All @@ -340,13 +345,27 @@ struct ICUDatePart : public ICUDateFunc {

bool Equals(const FunctionData &other_p) const override {
const auto &other = other_p.Cast<BindStructData>();
return BindData::Equals(other_p) && part_codes == other.part_codes && bigints == other.bigints &&
doubles == other.doubles;
return BindData::Equals(other_p) && part_codes == other.part_codes;
}

duckdb::unique_ptr<FunctionData> Copy() const override {
return make_uniq<BindStructData>(*this);
}

void InitFactories() {
bigints.clear();
bigints.resize(part_codes.size(), nullptr);
doubles.clear();
doubles.resize(part_codes.size(), nullptr);
for (size_t col = 0; col < part_codes.size(); ++col) {
const auto part_code = part_codes[col];
if (IsBigintDatepart(part_code)) {
bigints[col] = PartCodeBigintFactory(part_code);
} else {
doubles[col] = PartCodeDoubleFactory(part_code);
}
}
}
};

template <typename INPUT_TYPE>
Expand Down Expand Up @@ -504,8 +523,6 @@ struct ICUDatePart : public ICUDateFunc {
case_insensitive_set_t name_collision_set;
child_list_t<LogicalType> struct_children;
BindStructData::part_codes_t part_codes;
BindStructData::bigints_t bigints;
BindStructData::doubles_t doubles;

Value parts_list = ExpressionExecutor::EvaluateScalar(context, *arguments[0]);
if (parts_list.type().id() == LogicalTypeId::LIST) {
Expand All @@ -514,8 +531,6 @@ struct ICUDatePart : public ICUDateFunc {
throw BinderException("%s requires non-empty lists of part names", bound_function.name);
}

bigints.resize(list_children.size(), nullptr);
doubles.resize(list_children.size(), nullptr);
for (size_t col = 0; col < list_children.size(); ++col) {
const auto &part_value = list_children[col];
if (part_value.IsNull()) {
Expand All @@ -529,10 +544,8 @@ struct ICUDatePart : public ICUDateFunc {
name_collision_set.insert(part_name);
part_codes.emplace_back(part_code);
if (IsBigintDatepart(part_code)) {
bigints[col] = PartCodeBigintFactory(part_code);
struct_children.emplace_back(make_pair(part_name, LogicalType::BIGINT));
} else {
doubles[col] = PartCodeDoubleFactory(part_code);
struct_children.emplace_back(make_pair(part_name, LogicalType::DOUBLE));
}
}
Expand All @@ -542,17 +555,24 @@ struct ICUDatePart : public ICUDateFunc {

Function::EraseArgument(bound_function, arguments, 0);
bound_function.return_type = LogicalType::STRUCT(std::move(struct_children));
return make_uniq<BindStructData>(context, part_codes, bigints, doubles);
return make_uniq<BindStructData>(context, std::move(part_codes));
}

static void SerializeFunction(Serializer &serializer, const optional_ptr<FunctionData> bind_data,
const ScalarFunction &function) {
throw NotImplementedException("FIXME: serialize icu-datepart");
static void SerializeStructFunction(Serializer &serializer, const optional_ptr<FunctionData> bind_data,
const ScalarFunction &function) {
D_ASSERT(bind_data);
auto &info = bind_data->Cast<BindStructData>();
serializer.WriteProperty(100, "tz_setting", info.tz_setting);
serializer.WriteProperty(101, "cal_setting", info.cal_setting);
serializer.WriteProperty(102, "part_codes", info.part_codes);
}

static duckdb::unique_ptr<FunctionData> DeserializeFunction(Deserializer &deserializer,
ScalarFunction &bound_function) {
throw NotImplementedException("FIXME: serialize icu-datepart");
static duckdb::unique_ptr<FunctionData> DeserializeStructFunction(Deserializer &deserializer,
ScalarFunction &bound_function) {
auto tz_setting = deserializer.ReadProperty<string>(100, "tz_setting");
auto cal_setting = deserializer.ReadProperty<string>(101, "cal_setting");
auto part_codes = deserializer.ReadProperty<vector<DatePartSpecifier>>(102, "part_codes");
return make_uniq<BindStructData>(tz_setting, cal_setting, std::move(part_codes));
}

template <typename INPUT_TYPE, typename RESULT_TYPE>
Expand Down Expand Up @@ -581,8 +601,8 @@ struct ICUDatePart : public ICUDateFunc {
auto part_type = LogicalType::LIST(LogicalType::VARCHAR);
auto result_type = LogicalType::STRUCT({});
ScalarFunction result({part_type, temporal_type}, result_type, StructFunction<INPUT_TYPE>, BindStruct);
result.serialize = SerializeFunction;
result.deserialize = DeserializeFunction;
result.serialize = SerializeStructFunction;
result.deserialize = DeserializeStructFunction;
return result;
}

Expand Down
3 changes: 3 additions & 0 deletions extension/icu/include/icu-datefunc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct ICUDateFunc {

struct BindData : public FunctionData {
explicit BindData(ClientContext &context);
BindData(const string &tz_setting, const string &cal_setting);
BindData(const BindData &other);

string tz_setting;
Expand All @@ -29,6 +30,8 @@ struct ICUDateFunc {

bool Equals(const FunctionData &other_p) const override;
duckdb::unique_ptr<FunctionData> Copy() const override;

void InitCalendar();
};

struct CastData : public BoundCastData {
Expand Down