-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cleanup logical type construction #2571
Conversation
cfa5921
to
eb92eab
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #2571 +/- ##
=======================================
Coverage 93.15% 93.16%
=======================================
Files 1027 1027
Lines 38414 38363 -51
=======================================
- Hits 35785 35740 -45
+ Misses 2629 2623 -6 ☔ View full report in Codecov by Sentry. |
b9c5021
to
c216fc3
Compare
@@ -123,12 +123,12 @@ class AggregateFunctionUtil { | |||
static std::unique_ptr<AggregateFunction> getAvgFunc(const std::string name, | |||
common::LogicalTypeID inputType, common::LogicalTypeID resultType, bool isDistinct); | |||
static std::unique_ptr<AggregateFunction> getMinFunc( | |||
const common::LogicalType& inputType, bool isDistinct); | |||
common::LogicalTypeID inputType, bool isDistinct); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is fine in this PR. But in the long run, all functions (scalar, aggregation, table, ...) should have the same base class Function
whose parameters are LogicalType
rather than LogicalTypeID
which means we will be using LogicalType
almost everywhere for function related code path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly it seems weird to me to pass around versions of LogicalType
which have no extraTypeInfo
, even for complex types, particularly when LogicalTypeID
is functionally identical.
src/include/common/types/types.h
Outdated
@@ -287,80 +288,113 @@ class LogicalType { | |||
const std::vector<std::unique_ptr<LogicalType>>& types); | |||
|
|||
static std::unique_ptr<LogicalType> BOOL() { | |||
return std::make_unique<LogicalType>(LogicalTypeID::BOOL); | |||
return std::unique_ptr<LogicalType>(new LogicalType(LogicalTypeID::BOOL)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought make_unique
is preferred compared to std::unique_ptr<>(new object)
. Is there a reason that you are changing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd tried making the constructors private, but only the two-argument one still is. I can revert the change for the simple types, but make_unique doesn't work with private constructors.
I think we should just use unique_ptr everywhere or never use it. The former solution seems to be easier since we are already doing so in most places. |
@@ -3,6 +3,15 @@ | |||
|
|||
using namespace kuzu::common; | |||
|
|||
namespace kuzu::common { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This helper looks wired, should we provide this helper to the user? I will let @mewim comment on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just to give the C API (and there's a similar one for the java API) access to the private LogicalType constructor (using a wrapper class to make it easier to declare as friend in types.h).
Maybe we should set up per-type functions similar to the LogicalType ones for constructing types (or at least, for constructing the complex types).
@@ -239,7 +240,7 @@ class StructTypeInfo : public ExtraTypeInfo { | |||
void serializeInternal(Serializer& serializer) const override; | |||
|
|||
private: | |||
std::vector<std::unique_ptr<StructField>> fields; | |||
std::vector<StructField> fields; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we remove the unique_ptr here?
We always use vector<unique_ptr> to avoid unintentional copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There still is no possibility of an unintentional copy. StructField has no copy constructor (deleted implicitly since it contains a unique_ptr
: E.g.). Given that its purpose is just for creating struct types, I don't think it really needs one either, so we can just leave it as a move-only type.
8aaa65d
to
e7bfd2b
Compare
I've updated it to have them return |
e7bfd2b
to
1cdb4cc
Compare
1cdb4cc
to
3799d81
Compare
This reduces the amount of boiler-plate code that has to be written when creating logical types by moving that into
types.cpp
and providing more specific static methods to create the complex types, particularly since this is part of our public API and users don't really need to handleExtraTypeInfo
directly.E.g.
LogicalType::VAR_LIST(childType);
instead ofLogicalType(LogicalTypeID::VAR_LIST, std::make_unique<VarListTypeInfo>(childType));
.I'd also cleaned up a couple places where
LogicalType
was being used whereLogicalTypeID
could have been used instead, and removed some indirection fromStructField
to simplify it.Ideally I think the
ExtraTypeInfo
implementations could be hidden insidetypes.cpp
, however there are some more complex places, particularly forNODE
,REL
andRECURSIVE_REL
, which I'd left alone.One part I'm not sure about is the return types of the
LogicalType
static methods. The simple types all returnunique_ptr
(and the regular constructor is used in places where a unique_ptr is not wanted), but the complex types also need both, and it's a choice between:LogicalType::VAR_LIST_P
to produce a unique_ptr (or a separate method not to, for consistency with the simple types?).LogicalType
(what's implemented here), and if you want a unique_ptr wrap it withmake_unique<LogicalType>(...)
to move the object into theunique_ptr
using the move constructor.unique_ptr<LogicalType>
and usestd::move(*LogicalType::VAR_LIST(...))
to move the data out of theunique_ptr
if you want (unlike (2) this adds an unnecessary heap allocation).