Skip to content

Commit

Permalink
fix(codegen): handle nullable for date type (#3543)
Browse files Browse the repository at this point in the history
* fix(codegen): handle nullable for date type

Also fix include headers

* fix(codegen): handle nulls for date and timestamp

always returns allocated structure even it is null, for the cases:
1. construct timestamp from number, even number is < 0
2. construct date from timestamp, even timestamp is null
  • Loading branch information
aceforeverd authored Oct 23, 2023
1 parent 190992d commit 6fe2a30
Show file tree
Hide file tree
Showing 18 changed files with 76 additions and 83 deletions.
12 changes: 12 additions & 0 deletions cases/query/const_query.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,15 @@ cases:
columns: ['c1 bool', 'c2 int16', 'c3 int', 'c4 double', 'c5 string', 'c6 date', 'c7 timestamp' ]
rows:
- [ true, 3, 13, 10.0, 'a string', '2020-05-22', 1590115420000 ]
- id: 10
mode: procedure-unsupport
sql: |
select
datediff(Date(timestamp(-1)), Date("2021-05-01")) as out1,
datediff(Date(timestamp(-2177481600)), Date("2021-05-01")) as out2,
datediff(cast(NULL as date), Date("2021-05-01")) as out3
;
expect:
columns: ["out1 int", "out2 int", "out3 int"]
data: |
NULL, NULL, NULL
1 change: 1 addition & 0 deletions hybridse/src/codegen/array_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "codegen/array_ir_builder.h"

#include <string>
#include "codegen/ir_base_builder.h"

namespace hybridse {
namespace codegen {
Expand Down
5 changes: 5 additions & 0 deletions hybridse/src/codegen/cast_expr_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ Status CastExprIRBuilder::UnSafeCast(const NativeValue& value,
StringIRBuilder string_ir_builder(block_->getModule());
CHECK_STATUS(string_ir_builder.CreateNull(block_, output));
return base::Status::OK();

} else if (TypeIRBuilder::IsDatePtr(type)) {
DateIRBuilder date_ir(block_->getModule());
CHECK_STATUS(date_ir.CreateNull(block_, output));
return base::Status::OK();
} else {
*output = NativeValue::CreateNull(type);
}
Expand Down
19 changes: 14 additions & 5 deletions hybridse/src/codegen/date_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <vector>
#include "codegen/arithmetic_expr_ir_builder.h"
#include "codegen/ir_base_builder.h"
#include "codegen/null_ir_builder.h"

namespace hybridse {
namespace codegen {
Expand All @@ -43,6 +44,15 @@ void DateIRBuilder::InitStructType() {
struct_type_ = stype;
return;
}

base::Status DateIRBuilder::CreateNull(::llvm::BasicBlock* block, NativeValue* output) {
::llvm::Value* value = nullptr;
CHECK_TRUE(CreateDefault(block, &value), common::kCodegenError, "Fail to construct string")
::llvm::IRBuilder<> builder(block);
*output = NativeValue::CreateWithFlag(value, builder.getInt1(true));
return base::Status::OK();
}

bool DateIRBuilder::CreateDefault(::llvm::BasicBlock* block,
::llvm::Value** output) {
return NewDate(block, output);
Expand Down Expand Up @@ -123,11 +133,10 @@ base::Status DateIRBuilder::CastFrom(::llvm::BasicBlock* block,
auto cast_func = m_->getOrInsertFunction(
fn_name,
::llvm::FunctionType::get(builder.getVoidTy(),
{src.GetType(), dist->getType(),
builder.getInt1Ty()->getPointerTo()},
false));
builder.CreateCall(cast_func,
{src.GetValue(&builder), dist, is_null_ptr});
{src.GetType(), dist->getType(), builder.getInt1Ty()->getPointerTo()}, false));

builder.CreateCall(cast_func, {src.GetValue(&builder), dist, is_null_ptr});

::llvm::Value* should_return_null = builder.CreateLoad(is_null_ptr);
null_ir_builder.CheckAnyNull(block, src, &should_return_null);
*output = NativeValue::CreateWithFlag(dist, should_return_null);
Expand Down
22 changes: 9 additions & 13 deletions hybridse/src/codegen/date_ir_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@

#ifndef HYBRIDSE_SRC_CODEGEN_DATE_IR_BUILDER_H_
#define HYBRIDSE_SRC_CODEGEN_DATE_IR_BUILDER_H_

#include "base/fe_status.h"
#include "codegen/cast_expr_ir_builder.h"
#include "codegen/null_ir_builder.h"
#include "codegen/scope_var.h"
#include "codegen/struct_ir_builder.h"
#include "llvm/IR/IRBuilder.h"
#include "proto/fe_type.pb.h"

namespace hybridse {
namespace codegen {
Expand All @@ -31,17 +27,17 @@ class DateIRBuilder : public StructTypeIRBuilder {
public:
explicit DateIRBuilder(::llvm::Module* m);
~DateIRBuilder();
void InitStructType();
bool CreateDefault(::llvm::BasicBlock* block, ::llvm::Value** output);
void InitStructType() override;

base::Status CreateNull(::llvm::BasicBlock* block, NativeValue* output);
bool CreateDefault(::llvm::BasicBlock* block, ::llvm::Value** output) override;

bool NewDate(::llvm::BasicBlock* block, ::llvm::Value** output);
bool NewDate(::llvm::BasicBlock* block, ::llvm::Value* date,
::llvm::Value** output);
bool CopyFrom(::llvm::BasicBlock* block, ::llvm::Value* src,
::llvm::Value* dist);
base::Status CastFrom(::llvm::BasicBlock* block, const NativeValue& src,
NativeValue* output);
base::Status CastFrom(::llvm::BasicBlock* block, ::llvm::Value* src,
::llvm::Value** output);
bool CopyFrom(::llvm::BasicBlock* block, ::llvm::Value* src, ::llvm::Value* dist);
base::Status CastFrom(::llvm::BasicBlock* block, const NativeValue& src, NativeValue* output);

bool GetDate(::llvm::BasicBlock* block, ::llvm::Value* date,
::llvm::Value** output);
bool SetDate(::llvm::BasicBlock* block, ::llvm::Value* date,
Expand Down
1 change: 0 additions & 1 deletion hybridse/src/codegen/ir_base_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#include <string>
#include <vector>
#include "glog/logging.h"
#include "llvm/IR/IRBuilder.h"
#include "node/sql_node.h"
#include "node/type_node.h"
Expand Down
1 change: 0 additions & 1 deletion hybridse/src/codegen/native_value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "codegen/native_value.h"
#include <dlfcn.h>
#include <execinfo.h>
#include <signal.h>
#include "codegen/context.h"
#include "codegen/ir_base_builder.h"

Expand Down
1 change: 1 addition & 0 deletions hybridse/src/codegen/predicate_expr_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "codegen/predicate_expr_ir_builder.h"
#include "codegen/date_ir_builder.h"
#include "codegen/ir_base_builder.h"
#include "codegen/null_ir_builder.h"
#include "codegen/string_ir_builder.h"
#include "codegen/timestamp_ir_builder.h"
#include "codegen/type_ir_builder.h"
Expand Down
6 changes: 2 additions & 4 deletions hybridse/src/codegen/struct_ir_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@

#ifndef HYBRIDSE_SRC_CODEGEN_STRUCT_IR_BUILDER_H_
#define HYBRIDSE_SRC_CODEGEN_STRUCT_IR_BUILDER_H_

#include "base/fe_status.h"
#include "codegen/cast_expr_ir_builder.h"
#include "codegen/scope_var.h"
#include "codegen/native_value.h"
#include "codegen/type_ir_builder.h"
#include "llvm/IR/IRBuilder.h"
#include "proto/fe_type.pb.h"

namespace hybridse {
namespace codegen {
Expand Down
26 changes: 14 additions & 12 deletions hybridse/src/codegen/timestamp_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
*/

#include "codegen/timestamp_ir_builder.h"

#include <string>
#include <vector>

#include "codegen/arithmetic_expr_ir_builder.h"
#include "codegen/ir_base_builder.h"
#include "codegen/null_ir_builder.h"
#include "codegen/predicate_expr_ir_builder.h"
#include "glog/logging.h"
#include "node/sql_node.h"

using hybridse::common::kCodegenError;

Expand Down Expand Up @@ -70,29 +71,30 @@ base::Status TimestampIRBuilder::CastFrom(::llvm::BasicBlock* block,
CondSelectIRBuilder cond_ir_builder;
PredicateIRBuilder predicate_ir_builder(block);
NullIRBuilder null_ir_builder;

// always allocate for returned timestmap even it is null
::llvm::Value* dist = nullptr;
if (!CreateDefault(block, &dist)) {
status.code = common::kCodegenError;
status.msg = "Fail to cast date: create default date fail";
return status;
}

if (IsNumber(src.GetType())) {
CHECK_STATUS(cast_builder.Cast(src, builder.getInt64Ty(), &ts));
NativeValue cond;
CHECK_STATUS(predicate_ir_builder.BuildGeExpr(
ts, NativeValue::Create(builder.getInt64(0)), &cond));
::llvm::Value* timestamp;
CHECK_TRUE(NewTimestamp(block, ts.GetValue(&builder), &timestamp),
CHECK_TRUE(SetTs(block, dist, ts.GetValue(&builder)),
kCodegenError,
"Fail to cast timestamp: new timestamp(ts) fail");
CHECK_STATUS(
cond_ir_builder.Select(block, cond, NativeValue::Create(timestamp),
NativeValue::CreateNull(GetType()), output));
CHECK_STATUS(cond_ir_builder.Select(block, cond, NativeValue::Create(dist),
NativeValue::CreateWithFlag(dist, builder.getInt1(true)), output));

} else if (IsStringPtr(src.GetType()) || IsDatePtr(src.GetType())) {
::llvm::IRBuilder<> builder(block);
::llvm::Value* dist = nullptr;
::llvm::Value* is_null_ptr = CreateAllocaAtHead(
&builder, builder.getInt1Ty(), "timestamp_is_null_alloca");
if (!CreateDefault(block, &dist)) {
status.code = common::kCodegenError;
status.msg = "Fail to cast date: create default date fail";
return status;
}
::std::string fn_name = "timestamp." + TypeName(src.GetType());

auto cast_func = m_->getOrInsertFunction(
Expand Down
9 changes: 3 additions & 6 deletions hybridse/src/codegen/timestamp_ir_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@

#ifndef HYBRIDSE_SRC_CODEGEN_TIMESTAMP_IR_BUILDER_H_
#define HYBRIDSE_SRC_CODEGEN_TIMESTAMP_IR_BUILDER_H_

#include "base/fe_status.h"
#include "codegen/cast_expr_ir_builder.h"
#include "codegen/scope_var.h"
#include "codegen/struct_ir_builder.h"
#include "llvm/IR/IRBuilder.h"
#include "proto/fe_type.pb.h"

namespace hybridse {
namespace codegen {
Expand All @@ -33,8 +30,8 @@ class TimestampIRBuilder : public StructTypeIRBuilder {
void InitStructType();
bool CreateDefault(::llvm::BasicBlock* block, ::llvm::Value** output);
bool NewTimestamp(::llvm::BasicBlock* block, ::llvm::Value** output);
bool NewTimestamp(::llvm::BasicBlock* block, ::llvm::Value* ts,
::llvm::Value** output);
bool NewTimestamp(::llvm::BasicBlock* block, ::llvm::Value* ts, ::llvm::Value** output);

bool CopyFrom(::llvm::BasicBlock* block, ::llvm::Value* src,
::llvm::Value* dist);
base::Status CastFrom(::llvm::BasicBlock* block, const NativeValue& src,
Expand Down
1 change: 1 addition & 0 deletions hybridse/src/codegen/type_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "codegen/type_ir_builder.h"

#include "codegen/ir_base_builder.h"
#include "glog/logging.h"
#include "node/node_manager.h"
Expand Down
7 changes: 3 additions & 4 deletions hybridse/src/codegen/type_ir_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
#define HYBRIDSE_SRC_CODEGEN_TYPE_IR_BUILDER_H_

#include <string>
#include <vector>

#include "base/fe_status.h"
#include "codec/fe_row_codec.h"
#include "codegen/ir_base_builder.h"
#include "node/node_enum.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "node/sql_node.h"
#include "node/type_node.h"

Expand Down
12 changes: 5 additions & 7 deletions hybridse/src/codegen/udf_ir_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,17 @@
*/

#include "codegen/udf_ir_builder.h"
#include <iostream>
#include <utility>

#include <vector>

#include "codegen/context.h"
#include "codegen/date_ir_builder.h"
#include "codegen/fn_ir_builder.h"
#include "codegen/ir_base_builder.h"
#include "codegen/list_ir_builder.h"
#include "codegen/null_ir_builder.h"
#include "codegen/timestamp_ir_builder.h"
#include "codegen/type_ir_builder.h"
#include "llvm/IR/Attributes.h"
#include "node/node_manager.h"
#include "node/sql_node.h"
#include "udf/udf.h"
#include "udf/udf_registry.h"

using ::hybridse::common::kCodegenError;
Expand Down Expand Up @@ -162,7 +160,7 @@ Status UdfIRBuilder::BuildLambdaCall(
Status UdfIRBuilder::BuildCodeGenUdfCall(
const node::UdfByCodeGenDefNode* fn,
const std::vector<NativeValue>& args, NativeValue* output) {
auto gen_impl = fn->GetGenImpl();
std::shared_ptr<udf::LlvmUdfGenBase> gen_impl = fn->GetGenImpl();

::llvm::Value* ret_null = nullptr;
for (size_t i = 0; i < fn->GetArgSize(); ++i) {
Expand Down
4 changes: 0 additions & 4 deletions hybridse/src/codegen/udf_ir_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,9 @@
#ifndef HYBRIDSE_SRC_CODEGEN_UDF_IR_BUILDER_H_
#define HYBRIDSE_SRC_CODEGEN_UDF_IR_BUILDER_H_

#include <map>
#include <string>
#include <vector>
#include "base/fe_status.h"
#include "codegen/expr_ir_builder.h"
#include "codegen/scope_var.h"
#include "llvm/IR/Module.h"

#include "node/sql_node.h"
namespace hybridse {
Expand Down
13 changes: 2 additions & 11 deletions hybridse/src/udf/default_udf_library.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <queue>
#include <functional>

#include "absl/strings/str_cat.h"
#include "codegen/date_ir_builder.h"
#include "codegen/string_ir_builder.h"
#include "codegen/timestamp_ir_builder.h"
Expand Down Expand Up @@ -2169,11 +2168,7 @@ void DefaultUdfLibrary::InitTypeUdf() {
)");

RegisterExternal("date")
.args<Timestamp>(reinterpret_cast<void*>(
static_cast<void (*)(Timestamp*, Date*, bool*)>(
v1::timestamp_to_date)))
.return_by_arg(true)
.returns<Nullable<Date>>()
.args<Timestamp>(v1::timestamp_to_date)
.doc(R"(
@brief Cast timestamp or string expression to date (date >= 1900-01-01)
Expand All @@ -2192,11 +2187,7 @@ void DefaultUdfLibrary::InitTypeUdf() {
@endcode
@since 0.1.0)");
RegisterExternal("date")
.args<StringRef>(reinterpret_cast<void*>(
static_cast<void (*)(StringRef*, Date*, bool*)>(
v1::string_to_date)))
.return_by_arg(true)
.returns<Nullable<Date>>();
.args<StringRef>(v1::string_to_date);

RegisterExternal("timestamp")
.args<Date>(reinterpret_cast<void*>(
Expand Down
15 changes: 4 additions & 11 deletions hybridse/src/udf/udf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,24 @@
#include <time.h>

#include <ctime>
#include <map>
#include <set>
#include <utility>

#include "absl/strings/ascii.h"
#include "absl/strings/str_replace.h"
#include "absl/time/civil_time.h"
#include "absl/time/time.h"
#include "base/iterator.h"
#include "boost/date_time.hpp"
#include "boost/date_time/gregorian/conversion.hpp"
#include "boost/date_time/gregorian/parsers.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"
#include "bthread/types.h"
#include "codec/list_iterator_codec.h"
#include "codec/row.h"
#include "codec/type_codec.h"
#include "codegen/fn_ir_builder.h"
#include "farmhash.h"
#include "node/node_manager.h"
#include "node/sql_node.h"
#include "re2/re2.h"
#include "udf/default_udf_library.h"
#include "udf/literal_traits.h"
#include "udf/udf_library.h"
#include "vm/jit_runtime.h"

namespace hybridse {
Expand Down Expand Up @@ -394,8 +389,7 @@ void bool_to_string(bool v, StringRef *output) {
}
}

void timestamp_to_date(Timestamp *timestamp,
Date *output, bool *is_null) {
void timestamp_to_date(Timestamp *timestamp, Date *output, bool *is_null) {
time_t time = (timestamp->ts_ + TZ_OFFSET) / 1000;
struct tm t;
memset(&t, 0, sizeof(struct tm));
Expand Down Expand Up @@ -771,8 +765,7 @@ void string_to_double(StringRef *str, double *out, bool *is_null_ptr) {
}
return;
}
void string_to_date(StringRef *str, Date *output,
bool *is_null) {
void string_to_date(StringRef *str, Date *output, bool *is_null) {
if (19 == str->size_) {
struct tm timeinfo;
memset(&timeinfo, 0, sizeof(struct tm));
Expand Down
Loading

0 comments on commit 6fe2a30

Please sign in to comment.