logical::LogicalPtr apply(const logical::LogicalPtr &input) override {
    expressions::UnorderedAttributeSet inner_attributes;
    std::vector<expressions::AttributeReferencePtr> probe_join_attributes;
    std::vector<expressions::AttributeReferencePtr> build_join_attributes;
    std::vector<expressions::PredicatePtr> non_hash_join_predicates;

    const logical::LogicalPtr output =
        applyInternal(input,
                      &inner_attributes,
                      &probe_join_attributes,
                      &build_join_attributes,
                      &non_hash_join_predicates);

    probe_join_attributes_->insert(probe_join_attributes_->end(),
                                   probe_join_attributes.begin(),
                                   probe_join_attributes.end());
    build_join_attributes_->insert(build_join_attributes_->end(),
                                   build_join_attributes.begin(),
                                   build_join_attributes.end());
    correlated_non_hash_join_predicates_->insert(correlated_non_hash_join_predicates_->end(),
                                                 non_hash_join_predicates.begin(),
                                                 non_hash_join_predicates.end());

    return output;
  }
예제 #2
0
void TextureMapperAnimation::apply(Client& client)
{
    if (!isActive())
        return;

    double totalRunningTime = computeTotalRunningTime();
    double normalizedValue = normalizedAnimationValue(totalRunningTime, m_animation->duration(), m_animation->direction(), m_animation->iterationCount());

    if (m_animation->iterationCount() != Animation::IterationCountInfinite && totalRunningTime >= m_animation->duration() * m_animation->iterationCount()) {
        m_state = AnimationState::Stopped;
        m_pauseTime = 0;
        if (m_animation->fillsForwards())
            normalizedValue = normalizedAnimationValueForFillsForwards(m_animation->iterationCount(), m_animation->direction());
    }

    if (!normalizedValue) {
        applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), 0);
        return;
    }

    if (normalizedValue == 1.0) {
        applyInternal(client, m_keyframes.at(m_keyframes.size() - 2), m_keyframes.at(m_keyframes.size() - 1), 1);
        return;
    }
    if (m_keyframes.size() == 2) {
        const TimingFunction* timingFunction = timingFunctionForAnimationValue(m_keyframes.at(0), m_animation.get());
        normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration());
        applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), normalizedValue);
        return;
    }

    for (size_t i = 0; i < m_keyframes.size() - 1; ++i) {
        const AnimationValue& from = m_keyframes.at(i);
        const AnimationValue& to = m_keyframes.at(i + 1);
        if (from.keyTime() > normalizedValue || to.keyTime() < normalizedValue)
            continue;

        normalizedValue = (normalizedValue - from.keyTime()) / (to.keyTime() - from.keyTime());
        const TimingFunction* timingFunction = timingFunctionForAnimationValue(from, m_animation.get());
        normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration());
        applyInternal(client, from, to, normalizedValue);
        break;
    }
}
예제 #3
0
void GraphicsLayerAnimation::apply(Client* client)
{
    if (!isActive())
        return;

    double totalRunningTime = m_state == PausedState ? m_pauseTime : WTF::currentTime() - m_startTime;
    double normalizedValue = normalizedAnimationValue(totalRunningTime, m_animation->duration(), m_animation->direction(), m_animation->iterationCount());

    if (m_animation->iterationCount() != Animation::IterationCountInfinite && totalRunningTime >= m_animation->duration() * m_animation->iterationCount()) {
        setState(StoppedState);
        if (m_animation->fillsForwards())
            normalizedValue = normalizedAnimationValueForFillsForwards(m_animation->iterationCount(), m_animation->direction());
    }

    if (!normalizedValue) {
        applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), 0);
        return;
    }

    if (normalizedValue == 1.0) {
        applyInternal(client, m_keyframes.at(m_keyframes.size() - 2), m_keyframes.at(m_keyframes.size() - 1), 1);
        return;
    }
    if (m_keyframes.size() == 2) {
        const TimingFunction* timingFunction = timingFunctionForAnimationValue(m_keyframes.at(0), m_animation.get());
        normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration());
        applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), normalizedValue);
        return;
    }

    for (size_t i = 0; i < m_keyframes.size() - 1; ++i) {
        const AnimationValue* from = m_keyframes.at(i);
        const AnimationValue* to = m_keyframes.at(i + 1);
        if (from->keyTime() > normalizedValue || to->keyTime() < normalizedValue)
            continue;

        normalizedValue = (normalizedValue - from->keyTime()) / (to->keyTime() - from->keyTime());
        const TimingFunction* timingFunction = timingFunctionForAnimationValue(from, m_animation.get());
        normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration());
        applyInternal(client, from, to, normalizedValue);
        break;
    }
}
예제 #4
0
P::PhysicalPtr ReduceGroupByAttributes::apply(const P::PhysicalPtr &input) {
  DCHECK(input->getPhysicalType() == P::PhysicalType::kTopLevelPlan);
  cost_model_.reset(new cost::StarSchemaSimpleCostModel(
      std::static_pointer_cast<const P::TopLevelPlan>(input)->shared_subplans()));

  P::PhysicalPtr output = applyInternal(input);
  if (output != input) {
    output = PruneColumns().apply(output);
  }
  return output;
}
예제 #5
0
P::PhysicalPtr ReduceGroupByAttributes::applyInternal(const P::PhysicalPtr &input) {
  std::vector<P::PhysicalPtr> new_children;
  for (const P::PhysicalPtr &child : input->children()) {
    new_children.push_back(applyInternal(child));
  }

  if (new_children != input->children()) {
    return applyToNode(input->copyWithNewChildren(new_children));
  } else {
    return applyToNode(input);
  }
}
예제 #6
0
/*******************************************************************************
  If "node" is inside a UDF body, then "udfCaller" is the fo expr that invokes
  that UDF.
********************************************************************************/
void MarkNodeCopyProps::applyInternal(expr* node, bool deferred)
{
  static_context* sctx = node->get_sctx();

  switch (node->get_expr_kind())
  {
  case const_expr_kind:
  case var_expr_kind:
  case argument_placeholder_expr_kind:
  {
    return;
  }

  case doc_expr_kind:
  case elem_expr_kind:
  case attr_expr_kind:
  case namespace_expr_kind:
  case text_expr_kind:
  case pi_expr_kind:
  {
    // If a doc or element constructor needs to copy (and the ns mode is preserve
    // and inherit), should it be considered unsafe? The answer is no, because if
    // copy is needed, then any other construction done during the "current" one
    // will need to copy as well, so the input trees to the current constructor
    // will be standalone. This is enforced by the findNodeSources() method,
    // which drills down inside constructors and will collect as sources any
    // nested c onstructors as well.
    break;
  }

  case json_direct_object_expr_kind:
  {
    // For now, assume that nodes to appear as pair values must be copied first.
    // TODO improve this
    json_direct_object_expr* e = static_cast<json_direct_object_expr *>(node);

    if (sctx->preserve_ns() && sctx->inherit_ns())
    {
      csize numPairs = e->num_pairs();
      for (csize i = 0; i < numPairs; ++i)
      {
        std::vector<expr*> sources;
        theSourceFinder->findNodeSources(e->get_value_expr(i), sources);
        markSources(sources);
      }
    }

    break;
  }
  case json_object_expr_kind:
  {
    // The input to this expr is a sequence of other objects, which if they
    // contain any nodes, those nodes are in standalone trees. So, copying
    // these nodes when the objects are copied is ok.
    break;
  }
  case json_array_expr_kind:
  {
    // For now, assume that nodes to appear as members must be copied first.
    // TODO improve this
    json_array_expr* e = static_cast<json_array_expr *>(node);

    if (sctx->preserve_ns() && sctx->inherit_ns() && e->get_expr())
    {
      std::vector<expr*> sources;
      theSourceFinder->findNodeSources(e->get_expr(), sources);
      markSources(sources);
    }

    break;
  }
  case relpath_expr_kind:
  {
    relpath_expr* e = static_cast<relpath_expr *>(node);

    std::vector<expr*>::const_iterator ite = e->begin();
    std::vector<expr*>::const_iterator end = e->end();

    for (++ite; ite != end; ++ite)
    {
      axis_step_expr* axisExpr = static_cast<axis_step_expr*>((*ite));
      axis_kind_t axisKind = axisExpr->getAxis();

      if (axisKind != axis_kind_child &&
          axisKind != axis_kind_descendant &&
          axisKind != axis_kind_descendant_or_self &&
          axisKind != axis_kind_self &&
          axisKind != axis_kind_attribute)
      {
        std::vector<expr*> sources;
        theSourceFinder->findNodeSources((*e)[0], sources);
        markSources(sources);
        break;
      }
      else
      {
        match_expr* matchExpr = axisExpr->getTest();

        if (matchExpr->getTypeName() != NULL &&
            sctx->construction_mode() == StaticContextConsts::cons_strip)
        {
          std::vector<expr*> sources;
          theSourceFinder->findNodeSources((*e)[0], sources);
          markSources(sources);
          break;
        }
      }
    }

    applyInternal((*e)[0], deferred);

    return;
  }

  case fo_expr_kind:
  {
    fo_expr* e = static_cast<fo_expr *>(node);
    function* f = e->get_func();

    if (f->isUdf() && static_cast<user_function*>(f)->getBody() != NULL)
    {
      user_function* udf = static_cast<user_function*>(f);
      user_function* callerUdf = e->get_udf();

      bool recursive = (callerUdf ? callerUdf->isMutuallyRecursiveWith(udf) : false);

      if (recursive && !deferred)
      {
        callerUdf->addRecursiveCall(e);
      }
      else
      {
        UdfSet::iterator ite = theProcessedUDFs.find(udf);

        if (ite == theProcessedUDFs.end())
        {
          theProcessedUDFs.insert(udf);

          applyInternal(udf->getBody(), deferred);

          if (udf->isRecursive())
          {
            std::vector<fo_expr*>::const_iterator ite = udf->getRecursiveCalls().begin();
            std::vector<fo_expr*>::const_iterator end = udf->getRecursiveCalls().end();
            for (; ite != end; ++ite)
            {
              applyInternal(*ite, true);
            }
          }
        }

        // if an arg var of this udf has been marked as a source before, it
        // means that that var is consumed in some unsafe operation, so we
        // now have to find the sources of the arg expr and mark them.
        csize numArgs = e->num_args();

        for (csize i = 0; i < numArgs; ++i)
        {
          var_expr* argVar = udf->getArgVar(i);

          if (theSourceFinder->theVarSourcesMap.find(argVar) !=
              theSourceFinder->theVarSourcesMap.end())
          {
            std::vector<expr*> sources;
            theSourceFinder->findNodeSources(e->get_arg(i), sources);
            markSources(sources);
          }
        }
      }
    } // f->isUdf()
    else
    {
      csize numArgs = e->num_args();
      for (csize i = 0; i < numArgs; ++i)
      {
        if (f->mustCopyInputNodes(e, i))
        {
          std::vector<expr*> sources;
          theSourceFinder->findNodeSources(e->get_arg(i), sources);
          markSources(sources);
        }
      }

      FunctionConsts::FunctionKind fkind = f->getKind();

      switch (fkind)
      {
      case FunctionConsts::FN_DATA_1:
      case FunctionConsts::FN_NILLED_1:
      {
        if (sctx->construction_mode() == StaticContextConsts::cons_strip)
        {
          findSourcesForNodeExtractors(e->get_arg(0));
        }
        break;
      }
      case FunctionConsts::FN_BASE_URI_1:
      case FunctionConsts::FN_ROOT_1:
      // TODO: node-before, node-after
      {
        findSourcesForNodeExtractors(e->get_arg(0));
        break;
      }
      default:
        break;
      }
    }

    break;
  }

  case flwor_expr_kind:
  case if_expr_kind:
  case trycatch_expr_kind:

  case promote_expr_kind:

  case name_cast_expr_kind:
  case order_expr_kind:
  case wrapper_expr_kind:
  case function_trace_expr_kind:
  case extension_expr_kind:
  {
    break;
  }

  case castable_expr_kind:
  case cast_expr_kind:
  case instanceof_expr_kind:
  case treat_expr_kind:
  {
    if (sctx->construction_mode() == StaticContextConsts::cons_strip)
    {
      cast_or_castable_base_expr* e = static_cast<cast_or_castable_base_expr*>(node);

      findSourcesForNodeExtractors(e->get_input());
    }

    break;
  }

  case validate_expr_kind:
  {
    validate_expr* e = static_cast<validate_expr *>(node);
    std::vector<expr*> sources;
    theSourceFinder->findNodeSources(e->get_input(), sources);
    markSources(sources);
    break;
  }

  case delete_expr_kind:
  case rename_expr_kind:
  case insert_expr_kind:
  case replace_expr_kind:
  {
    update_expr_base* e = static_cast<update_expr_base*>(node);
    expr_kind_t kind = e->get_expr_kind();

    // The target node cannot be a shared node because the update would be seen
    // by multiple trees. For updates that delete nodes (delete and replace), the
    // whole tree must be standalone because we have to sum up the reference
    // counts of all the nodes in the delete subtree and that won't work if the
    // deleted subtree contains shared nodes.
    if (kind == replace_expr_kind || kind == delete_expr_kind)
    {
      std::vector<expr*> sources;
      theSourceFinder->findNodeSources(e->getTargetExpr(), sources);
      markSources(sources);
    }
    else
    {
      findSourcesForNodeExtractors(node);
    }

    // TODO: apply no-copy rule to insert and replace updates
    if (e->getSourceExpr() != NULL &&
        (kind == insert_expr_kind ||
         (kind == replace_expr_kind &&
          static_cast<replace_expr*>(e)->getType() == store::UpdateConsts::NODE)) &&
        sctx->inherit_ns() &&
        sctx->preserve_ns())
    {
      std::vector<expr*> sources;
      theSourceFinder->findNodeSources(e->getSourceExpr(), sources);
      markSources(sources);
    }

    break;
  }

  case transform_expr_kind:
  {
    transform_expr* e = static_cast<transform_expr *>(node);

    if (sctx->preserve_ns() && sctx->inherit_ns())
    {
      std::vector<copy_clause*>::const_iterator ite = e->begin();
      std::vector<copy_clause*>::const_iterator end = e->end();

      for (; ite != end; ++ite)
      {
        std::vector<expr*> sources;
        theSourceFinder->findNodeSources((*ite)->getExpr(), sources);
        markSources(sources);
      }
    }

    break;
  }

  case var_decl_expr_kind:
  case var_set_expr_kind:
  case apply_expr_kind:
  case while_expr_kind:
  case flowctl_expr_kind:
  case exit_expr_kind:
  case exit_catcher_expr_kind:
  case block_expr_kind:
  {
    break;
  }

  case eval_expr_kind:
  {
    eval_expr* e = static_cast<eval_expr*>(node);

    // Conservatively assume that, when executed, the eval query will apply
    // a "node-id-sensitive" operation on each of the in-scope variables, so
    // these variables must be bound to statndalone trees.
    csize numEvalVars = e->num_vars();

    for (csize i = 0; i < numEvalVars; ++i)
    {
      expr* arg = e->get_arg_expr(i);

      std::vector<expr*> sources;
      theSourceFinder->findNodeSources(arg, sources);
      markSources(sources);
    }

    break;
  }

  case debugger_expr_kind:
  {
    break;
  }

#ifndef ZORBA_NO_FULL_TEXT
  case ft_expr_kind:
  {
    // This expr prefrorms whole-tree tokenization. So, its input nodes
    // must not be shared nodes. What if the input nodes are not shared?
    // if ft_expr safe in that case ????
    ftcontains_expr* e = static_cast<ftcontains_expr*>(node);

    std::vector<expr*> sources;
    theSourceFinder->findNodeSources(e->get_range(), sources);
    markSources(sources);

    break;
  }
#endif

  case dynamic_function_invocation_expr_kind:
  {
    // Conservatively assume that the function item that is going to be executed
    // requires stand-alone trees as inputs, so find and mark the sources in the
    // arguments. TODO: look for function_item_expr in the subtree to check if
    // this assumption is really true.
    dynamic_function_invocation_expr* e =
    static_cast<dynamic_function_invocation_expr*>(node);

    const std::vector<expr*>& args = e->get_args();

    FOR_EACH(std::vector<expr*>, ite, args)
    {
      std::vector<expr*> sources;
      theSourceFinder->findNodeSources((*ite), sources);
      markSources(sources);
    }

    break;
  }

  case function_item_expr_kind:
  {
    function_item_expr* e = static_cast<function_item_expr*>(node);

    user_function* udf = static_cast<user_function*>(e->get_function());

    applyInternal(udf->getBody(), deferred);

    return;
  }

  case axis_step_expr_kind:
  case match_expr_kind:
  default:
    ZORBA_ASSERT(false);
  }
예제 #7
0
expr* MarkNodeCopyProps::apply(
    RewriterContext& rCtx,
    expr* node,
    bool& modified)
{
  modified = false;

  theSourceFinder = new SourceFinder;

  try
  {
    if (rCtx.theForSerializationOnly)
    {
      // Serialization may or may not be a "safe" op.
      static_context* sctx = node->get_sctx();

      if (sctx->preserve_ns())
      {
        if (sctx->inherit_ns())
        {
          // In this case, the result of the query should not contain any shared
          // node N, because if N was reached via a referencing tree, then
          // serializing N will miss the namespace bindings that N would have
          // inherited from the referencing tree if N had been copied into that
          // tree. (On the other hand it is ok if the query result contains nodes
          // which are not shared but have shared descendants). To handle this,
          // we call markInUnsafeContext() so that any exprs that (a) extract nodes
          // out of input nodes and (b) may propagate the extracted nodes to the
          // query result will be considered as unsafe and thus require that
          // their input trees are standalone.
          findSourcesForNodeExtractors(node);
        }
      }
      else
      {
        // In this case serialization is always unsafe.
        std::vector<expr*> sources;
        theSourceFinder->findNodeSources(rCtx.theRoot, sources);
        markSources(sources);
      }
    }
    else
    {
      // We have to assume that the result of the "node" expr will be used in an
      // unsafe op, so it must consist of standalone trees.
      std::vector<expr*> sources;
      theSourceFinder->findNodeSources(rCtx.theRoot, sources);
      markSources(sources);
    }

    applyInternal(node, false);
  }
  catch (...)
  {
    delete theSourceFinder;
    theSourceFinder = NULL;

    throw;
  }

  delete theSourceFinder;
  theSourceFinder = NULL;

  return NULL;
}
 expressions::ExpressionPtr apply(const expressions::ExpressionPtr &node) override {
   return applyInternal(true /* allow_exists_or_in */,
                        node);
 }