OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction Class Reference
+ Inheritance diagram for anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction:
+ Collaboration diagram for anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction:

Public Types

enum  WindowExprType { WindowExprType::PARTITION_KEY, WindowExprType::ORDER_KEY }
 

Public Member Functions

 PushDownGenericExpressionInWindowFunction (std::shared_ptr< RelProject > new_project, std::vector< std::unique_ptr< const RexScalar >> &scalar_exprs_for_new_project, std::vector< std::string > &fields_for_new_project, std::unordered_map< size_t, size_t > &expr_offset_cache)
 
size_t pushDownExpressionImpl (const RexScalar *expr) const
 
std::optional< size_t > getOffsetForPushedDownExpr (WindowExprType type, size_t expr_offset) const
 
void pushDownExpressionInWindowFunction (const RexWindowFunctionOperator *window_expr) const
 
std::unique_ptr< const RexScalarvisitInput (const RexInput *rex_input) const override
 
std::unique_ptr< const RexScalarvisitLiteral (const RexLiteral *rex_literal) const override
 
std::unique_ptr< const RexScalarvisitRef (const RexRef *rex_ref) const override
 
std::unique_ptr< const RexScalarvisitSubQuery (const RexSubQuery *rex_subquery) const override
 
std::unique_ptr< const RexScalarvisitCase (const RexCase *rex_case) const override
 
std::unique_ptr< const RexScalarvisitOperator (const RexOperator *rex_operator) const override
 
bool hasCaseExprAsWindowOperand ()
 
bool hasPartitionExpression ()
 
- Public Member Functions inherited from RexVisitorBase< std::unique_ptr< const RexScalar > >
virtual std::unique_ptr< const
RexScalar
visit (const RexScalar *rex_scalar) const
 

Private Member Functions

std::unique_ptr< const RexScalardefaultResult () const override
 

Private Attributes

std::shared_ptr< RelProjectnew_project_
 
std::vector< std::unique_ptr
< const RexScalar > > & 
scalar_exprs_for_new_project_
 
std::vector< std::string > & fields_for_new_project_
 
std::unordered_map< size_t,
size_t > & 
expr_offset_cache_
 
bool found_case_expr_window_operand_
 
bool has_partition_expr_
 
std::unordered_map< size_t,
size_t > 
pushed_down_window_operands_offset_
 
std::unordered_map< size_t,
size_t > 
pushed_down_partition_key_offset_
 
std::unordered_map< size_t,
size_t > 
pushed_down_order_key_offset_
 
RexDeepCopyVisitor deep_copier_
 

Additional Inherited Members

Detailed Description

Definition at line 125 of file RelAlgDag.cpp.

Member Enumeration Documentation

enum anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::WindowExprType
strong
Enumerator
PARTITION_KEY 
ORDER_KEY 

Definition at line 128 of file RelAlgDag.cpp.

128 { PARTITION_KEY, ORDER_KEY };

Constructor & Destructor Documentation

anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::PushDownGenericExpressionInWindowFunction ( std::shared_ptr< RelProject new_project,
std::vector< std::unique_ptr< const RexScalar >> &  scalar_exprs_for_new_project,
std::vector< std::string > &  fields_for_new_project,
std::unordered_map< size_t, size_t > &  expr_offset_cache 
)
inline

Member Function Documentation

std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::defaultResult ( ) const
inlineoverrideprivatevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 330 of file RelAlgDag.cpp.

330 { return nullptr; }
std::optional<size_t> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::getOffsetForPushedDownExpr ( WindowExprType  type,
size_t  expr_offset 
) const
inline

Definition at line 158 of file RelAlgDag.cpp.

References CHECK, and UNREACHABLE.

159  {
160  // given window expr offset and inner expr's offset,
161  // return a (push-downed) expression's offset from the new projection node
162  switch (type) {
164  auto it = pushed_down_partition_key_offset_.find(expr_offset);
166  return it->second;
167  }
169  auto it = pushed_down_order_key_offset_.find(expr_offset);
171  return it->second;
172  }
173  default:
174  UNREACHABLE();
175  return std::nullopt;
176  }
177  }
#define UNREACHABLE()
Definition: Logger.h:338
#define CHECK(condition)
Definition: Logger.h:291
bool anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::hasCaseExprAsWindowOperand ( )
inline
bool anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::hasPartitionExpression ( )
inline
size_t anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::pushDownExpressionImpl ( const RexScalar expr) const
inline

Definition at line 141 of file RelAlgDag.cpp.

References CHECK, and Rex::toHash().

141  {
142  auto hash = expr->toHash();
143  auto it = expr_offset_cache_.find(hash);
144  auto new_offset = -1;
145  if (it == expr_offset_cache_.end()) {
146  CHECK(
147  expr_offset_cache_.emplace(hash, scalar_exprs_for_new_project_.size()).second);
148  new_offset = scalar_exprs_for_new_project_.size();
149  fields_for_new_project_.emplace_back("");
151  } else {
152  // we already pushed down the same expression, so reuse it
153  new_offset = it->second;
154  }
155  return new_offset;
156  }
std::vector< std::unique_ptr< const RexScalar > > & scalar_exprs_for_new_project_
Definition: RelAlgDag.cpp:333
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
#define CHECK(condition)
Definition: Logger.h:291
virtual size_t toHash() const =0

+ Here is the call graph for this function:

void anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::pushDownExpressionInWindowFunction ( const RexWindowFunctionOperator window_expr) const
inline

Definition at line 179 of file RelAlgDag.cpp.

References CHECK, RexOperator::getOperand(), RexWindowFunctionOperator::getOrderKeys(), RexWindowFunctionOperator::getPartitionKeys(), and RexOperator::size().

180  {
181  // step 1. push "all" target expressions of the window_func_project_node down to the
182  // new child projection
183  // each window expr is a separate target expression of the projection node
184  // and they have their own inner expression related to partition / order clauses
185  // so we capture their offsets to correctly rebind their input
189  for (size_t offset = 0; offset < window_expr->size(); ++offset) {
190  auto expr = window_expr->getOperand(offset);
191  auto literal_expr = dynamic_cast<const RexLiteral*>(expr);
192  auto case_expr = dynamic_cast<const RexCase*>(expr);
193  if (case_expr) {
194  // when columnar output is enabled, pushdown case expr can incur an issue
195  // during columnarization, so we record this and try to force rowwise-output
196  // until we fix the issue
197  // todo (yoonmin) : relax this
199  }
200  if (!literal_expr) {
201  auto new_offset = pushDownExpressionImpl(expr);
202  pushed_down_window_operands_offset_.emplace(offset, new_offset);
203  }
204  }
205  size_t offset = 0;
206  for (const auto& partition_key : window_expr->getPartitionKeys()) {
207  auto new_offset = pushDownExpressionImpl(partition_key.get());
208  pushed_down_partition_key_offset_.emplace(offset, new_offset);
209  ++offset;
210  }
211  has_partition_expr_ = !window_expr->getPartitionKeys().empty();
212  offset = 0;
213  for (const auto& order_key : window_expr->getOrderKeys()) {
214  auto new_offset = pushDownExpressionImpl(order_key.get());
215  pushed_down_order_key_offset_.emplace(offset, new_offset);
216  ++offset;
217  }
218 
219  // step 2. rebind projected targets of the window_func_project_node with the new
220  // project node
221  std::vector<std::unique_ptr<const RexScalar>> window_operands;
222  auto deconst_window_expr = const_cast<RexWindowFunctionOperator*>(window_expr);
223  for (size_t idx = 0; idx < window_expr->size(); ++idx) {
224  auto it = pushed_down_window_operands_offset_.find(idx);
225  if (it != pushed_down_window_operands_offset_.end()) {
226  auto new_input = std::make_unique<const RexInput>(new_project_.get(), it->second);
227  CHECK(new_input);
228  window_operands.emplace_back(std::move(new_input));
229  } else {
230  auto copied_expr = deep_copier_.visit(window_expr->getOperand(idx));
231  window_operands.emplace_back(std::move(copied_expr));
232  }
233  }
234  deconst_window_expr->replaceOperands(std::move(window_operands));
235 
236  for (size_t idx = 0; idx < window_expr->getPartitionKeys().size(); ++idx) {
238  CHECK(new_offset);
239  auto new_input = std::make_unique<const RexInput>(new_project_.get(), *new_offset);
240  CHECK(new_input);
241  deconst_window_expr->replacePartitionKey(idx, std::move(new_input));
242  }
243 
244  for (size_t idx = 0; idx < window_expr->getOrderKeys().size(); ++idx) {
246  CHECK(new_offset);
247  auto new_input = std::make_unique<const RexInput>(new_project_.get(), *new_offset);
248  CHECK(new_input);
249  deconst_window_expr->replaceOrderKey(idx, std::move(new_input));
250  }
251  }
std::optional< size_t > getOffsetForPushedDownExpr(WindowExprType type, size_t expr_offset) const
Definition: RelAlgDag.cpp:158
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
const ConstRexScalarPtrVector & getPartitionKeys() const
Definition: RelAlgDag.h:643
#define CHECK(condition)
Definition: Logger.h:291
const ConstRexScalarPtrVector & getOrderKeys() const
Definition: RelAlgDag.h:653

+ Here is the call graph for this function:

std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::visitCase ( const RexCase rex_case) const
inlineoverridevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 279 of file RelAlgDag.cpp.

References RexCase::branchCount(), RexCase::getElse(), RexCase::getThen(), and RexCase::getWhen().

279  {
280  std::vector<
281  std::pair<std::unique_ptr<const RexScalar>, std::unique_ptr<const RexScalar>>>
282  new_expr_pair_list;
283  std::unique_ptr<const RexScalar> new_else_expr;
284  for (size_t i = 0; i < rex_case->branchCount(); ++i) {
285  const auto when = rex_case->getWhen(i);
287  const auto then = rex_case->getThen(i);
289  new_expr_pair_list.emplace_back(std::move(new_when), std::move(new_then));
290  }
291  if (rex_case->getElse()) {
292  new_else_expr = deep_copier_.visit(rex_case->getElse());
293  }
294  auto new_case = std::make_unique<const RexCase>(new_expr_pair_list, new_else_expr);
295  return new_case;
296  }
const RexScalar * getThen(const size_t idx) const
Definition: RelAlgDag.h:440
const RexScalar * getElse() const
Definition: RelAlgDag.h:445
const RexScalar * getWhen(const size_t idx) const
Definition: RelAlgDag.h:435
virtual std::unique_ptr< const RexScalar > visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
size_t branchCount() const
Definition: RelAlgDag.h:433

+ Here is the call graph for this function:

std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::visitInput ( const RexInput rex_input) const
inlineoverridevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 253 of file RelAlgDag.cpp.

References CHECK, CHECK_EQ, CHECK_LT, and RexInput::toHash().

253  {
254  auto new_offset = pushDownExpressionImpl(rex_input);
255  CHECK_LT(new_offset, scalar_exprs_for_new_project_.size());
256  auto hash = rex_input->toHash();
257  auto it = expr_offset_cache_.find(hash);
258  CHECK(it != expr_offset_cache_.end());
259  CHECK_EQ(new_offset, it->second);
260  auto new_input = std::make_unique<const RexInput>(new_project_.get(), new_offset);
261  CHECK(new_input);
262  return new_input;
263  }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::vector< std::unique_ptr< const RexScalar > > & scalar_exprs_for_new_project_
Definition: RelAlgDag.cpp:333
#define CHECK_LT(x, y)
Definition: Logger.h:303
virtual size_t toHash() const override
Definition: RelAlgDag.h:1074
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::visitLiteral ( const RexLiteral rex_literal) const
inlineoverridevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 265 of file RelAlgDag.cpp.

266  {
267  return deep_copier_.visit(rex_literal);
268  }
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::visitOperator ( const RexOperator rex_operator) const
inlineoverridevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 298 of file RelAlgDag.cpp.

References CHECK, RexOperator::getOperand(), RexOperator::getOperator(), RexOperator::getType(), and RexOperator::size().

299  {
300  const auto rex_window_func_operator =
301  dynamic_cast<const RexWindowFunctionOperator*>(rex_operator);
302  if (rex_window_func_operator) {
303  pushDownExpressionInWindowFunction(rex_window_func_operator);
304  return deep_copier_.visit(rex_operator);
305  } else {
306  std::unique_ptr<const RexOperator> new_operator{nullptr};
307  std::vector<std::unique_ptr<const RexScalar>> new_operands;
308  for (size_t i = 0; i < rex_operator->size(); ++i) {
309  const auto operand = rex_operator->getOperand(i);
310  auto new_operand = PushDownGenericExpressionInWindowFunction::visit(operand);
311  new_operands.emplace_back(std::move(new_operand));
312  }
313  if (auto function_op = dynamic_cast<const RexFunctionOperator*>(rex_operator)) {
314  new_operator = std::make_unique<const RexFunctionOperator>(
315  function_op->getName(), new_operands, rex_operator->getType());
316  } else {
317  new_operator = std::make_unique<const RexOperator>(
318  rex_operator->getOperator(), new_operands, rex_operator->getType());
319  }
320  CHECK(new_operator);
321  return new_operator;
322  }
323  }
const SQLTypeInfo & getType() const
Definition: RelAlgDag.h:378
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
void pushDownExpressionInWindowFunction(const RexWindowFunctionOperator *window_expr) const
Definition: RelAlgDag.cpp:179
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
SQLOps getOperator() const
Definition: RelAlgDag.h:376
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::visitRef ( const RexRef rex_ref) const
inlineoverridevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 270 of file RelAlgDag.cpp.

270  {
271  return deep_copier_.visit(rex_ref);
272  }
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27
std::unique_ptr<const RexScalar> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::visitSubQuery ( const RexSubQuery rex_subquery) const
inlineoverridevirtual

Implements RexVisitorBase< std::unique_ptr< const RexScalar > >.

Definition at line 274 of file RelAlgDag.cpp.

275  {
276  return deep_copier_.visit(rex_subquery);
277  }
virtual T visit(const RexScalar *rex_scalar) const
Definition: RexVisitor.h:27

Member Data Documentation

RexDeepCopyVisitor anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::deep_copier_
private

Definition at line 341 of file RelAlgDag.cpp.

std::unordered_map<size_t, size_t>& anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::expr_offset_cache_
private

Definition at line 335 of file RelAlgDag.cpp.

std::vector<std::string>& anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::fields_for_new_project_
private

Definition at line 334 of file RelAlgDag.cpp.

bool anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::found_case_expr_window_operand_
mutableprivate

Definition at line 336 of file RelAlgDag.cpp.

bool anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::has_partition_expr_
mutableprivate

Definition at line 337 of file RelAlgDag.cpp.

std::shared_ptr<RelProject> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::new_project_
private

Definition at line 332 of file RelAlgDag.cpp.

std::unordered_map<size_t, size_t> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::pushed_down_order_key_offset_
mutableprivate

Definition at line 340 of file RelAlgDag.cpp.

std::unordered_map<size_t, size_t> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::pushed_down_partition_key_offset_
mutableprivate

Definition at line 339 of file RelAlgDag.cpp.

std::unordered_map<size_t, size_t> anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::pushed_down_window_operands_offset_
mutableprivate

Definition at line 338 of file RelAlgDag.cpp.

std::vector<std::unique_ptr<const RexScalar> >& anonymous_namespace{RelAlgDag.cpp}::PushDownGenericExpressionInWindowFunction::scalar_exprs_for_new_project_
private

Definition at line 333 of file RelAlgDag.cpp.


The documentation for this class was generated from the following file: