Package org.teiid.query.processor.relational

Source Code of org.teiid.query.processor.relational.AccessNode

/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.query.processor.relational;

import static org.teiid.query.analysis.AnalysisRecord.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.client.plan.PlanNode;
import org.teiid.common.buffer.BlockedException;
import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.TupleBatch;
import org.teiid.common.buffer.TupleSource;
import org.teiid.common.buffer.BufferManager.BufferReserveMode;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.query.QueryPlugin;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.util.CommandContext;


public class AccessNode extends SubqueryAwareRelationalNode {

    private static final int MAX_CONCURRENT = 10; //TODO: this could be settable via a property
  // Initialization state
    private Command command;
    private String modelName;
    private String connectorBindingId;
    private boolean shouldEvaluate = false;

    // Processing state
  private ArrayList<TupleSource> tupleSources = new ArrayList<TupleSource>();
  private boolean isUpdate = false;
    private boolean returnedRows = false;
    protected Command nextCommand;
    private int reserved;
    private int schemaSize;
   
    protected AccessNode() {
    super();
  }
   
  public AccessNode(int nodeID) {
    super(nodeID);
  }
 
  @Override
  public void initialize(CommandContext context, BufferManager bufferManager,
      ProcessorDataManager dataMgr) {
    super.initialize(context, bufferManager, dataMgr);
      this.schemaSize = getBufferManager().getSchemaSize(getOutputElements());
  }

    public void reset() {
        super.reset();
        this.tupleSources.clear();
    isUpdate = false;
        returnedRows = false;
        nextCommand = null;
    }

  public void setCommand(Command command) {
    this.command = command;
  }

    public Command getCommand() {
        return this.command;
    }

  public void setModelName(String name) {
    this.modelName = name;
  }

  public String getModelName() {
    return this.modelName;
  }

    public void setShouldEvaluateExpressions(boolean shouldEvaluate) {
        this.shouldEvaluate = shouldEvaluate;
    }

  public void open()
    throws TeiidComponentException, TeiidProcessingException {

        // Copy command and resolve references if necessary
        Command atomicCommand = command;
        boolean needProcessing = true;
       
        if (shouldEvaluate) {
          atomicCommand = initialCommand();
        }
        do {
      atomicCommand = nextCommand();
          if(shouldEvaluate) {
              needProcessing = prepareNextCommand(atomicCommand);
              nextCommand = null;
          } else {
              needProcessing = RelationalNodeUtil.shouldExecute(atomicCommand, true);
          }
          // else command will not be changed, so no reason to all this work.
          // Removing this if block and always evaluating has a significant cost that will
          // show up in performance tests for many simple tests that do not require it.
         
          isUpdate = RelationalNodeUtil.isUpdate(atomicCommand);
         
      if(needProcessing) {
        registerRequest(atomicCommand);
      }
      //We hardcode an upper limit on currency because these commands have potentially large in-memory value sets
        } while (!processCommandsIndividually() && hasNextCommand() && this.tupleSources.size() < Math.min(MAX_CONCURRENT, this.getContext().getUserRequestSourceConcurrency()));
  }

  static void rewriteAndEvaluate(Command atomicCommand, Evaluator eval, CommandContext context, QueryMetadataInterface metadata)
      throws TeiidProcessingException, TeiidComponentException {
    try {
        // Defect 16059 - Rewrite the command to replace references, etc. with values.
      QueryRewriter.evaluateAndRewrite(atomicCommand, eval, context, metadata);
    } catch (QueryValidatorException e) {
        throw new TeiidProcessingException(e, QueryPlugin.Util.getString("AccessNode.rewrite_failed", atomicCommand)); //$NON-NLS-1$
    }
  }
 
  @SuppressWarnings("unused")
  protected Command initialCommand() throws TeiidProcessingException, TeiidComponentException {
    return nextCommand();
  }

  protected Command nextCommand() {
    //it's important to save the next command
    //to ensure that the subquery ids remain stable
    if (nextCommand == null) {
      nextCommand = (Command) command.clone();
    }
    return nextCommand;
  }

    protected boolean prepareNextCommand(Command atomicCommand) throws TeiidComponentException, TeiidProcessingException {
    rewriteAndEvaluate(atomicCommand, getEvaluator(Collections.emptyMap()), this.getContext(), this.getContext().getMetadata());
      return RelationalNodeUtil.shouldExecute(atomicCommand, true);
    }

  public TupleBatch nextBatchDirect()
    throws BlockedException, TeiidComponentException, TeiidProcessingException {
       
        while (!tupleSources.isEmpty() || hasNextCommand()) {
         
          if (tupleSources.isEmpty() && processCommandsIndividually()) {
            registerNext();
          }
         
          //drain the tuple source(s)
          for (int i = 0; i < this.tupleSources.size(); i++) {
            TupleSource tupleSource = tupleSources.get(i);
            try {
              List<?> tuple = null;
             
              while ((tuple = tupleSource.nextTuple()) != null) {
                      returnedRows = true;
                      addBatchRow(tuple);
                     
                      if (isBatchFull()) {
                        return pullBatch();
                      }
              }
             
                  //end of source
                    tupleSource.closeSource();
                    tupleSources.remove(i--);
                if (reserved > 0) {
                      reserved -= schemaSize;
                      getBufferManager().releaseBuffers(schemaSize);
                }
                    if (!processCommandsIndividually()) {
                      registerNext();
                    }
                    continue;
            } catch (BlockedException e) {
              if (processCommandsIndividually()) {
                throw e;
              }
              continue;
            }
      }
         
          if (processCommandsIndividually()) {
            if (hasPendingRows()) {
              return pullBatch();
            }
            continue;
          }
         
          if (!this.tupleSources.isEmpty()) {
            throw BlockedException.INSTANCE;
          }
        }
       
        if(isUpdate && !returnedRows) {
      List<Integer> tuple = new ArrayList<Integer>(1);
      tuple.add(Integer.valueOf(0));
            // Add tuple to current batch
            addBatchRow(tuple);
        }
        terminateBatches();
        return pullBatch();
  }

  private void registerNext() throws TeiidComponentException,
      TeiidProcessingException {
    while (hasNextCommand()) {
        Command atomicCommand = nextCommand();
        if (prepareNextCommand(atomicCommand)) {
          nextCommand = null;
            registerRequest(atomicCommand);
            break;
        }
        nextCommand = null;
    }
  }

  private void registerRequest(Command atomicCommand)
      throws TeiidComponentException, TeiidProcessingException {
    int limit = -1;
    if (getParent() instanceof LimitNode) {
      LimitNode parent = (LimitNode)getParent();
      if (parent.getLimit() > 0) {
        limit = parent.getLimit() + parent.getOffset();
      }
    }
    tupleSources.add(getDataManager().registerRequest(getContext(), atomicCommand, modelName, connectorBindingId, getID(), limit));
    if (tupleSources.size() > 1) {
          reserved += getBufferManager().reserveBuffers(schemaSize, BufferReserveMode.FORCE);
    }
  }
 
  protected boolean processCommandsIndividually() {
    return false;
  }
   
    protected boolean hasNextCommand() {
        return false;
    }
   
  public void closeDirect() {
      getBufferManager().releaseBuffers(reserved);
      reserved = 0;
    super.closeDirect();
        closeSources();           
  }

    private void closeSources() {
      for (TupleSource ts : this.tupleSources) {
        ts.closeSource();     
    }
      this.tupleSources.clear();
  }

  protected void getNodeString(StringBuffer str) {
    super.getNodeString(str);
    str.append(command);
  }

  public Object clone(){
    AccessNode clonedNode = new AccessNode();
    this.copy(this, clonedNode);
    return clonedNode;
  }

  protected void copy(AccessNode source, AccessNode target){
    super.copy(source, target);
    target.modelName = source.modelName;
    target.connectorBindingId = source.connectorBindingId;
    target.shouldEvaluate = source.shouldEvaluate;
    target.command = source.command;
  }

    public PlanNode getDescriptionProperties() {
      PlanNode props = super.getDescriptionProperties();
        props.addProperty(PROP_SQL, this.command.toString());
        props.addProperty(PROP_MODEL_NAME, this.modelName);
        return props;
    }

  public String getConnectorBindingId() {
    return connectorBindingId;
  }

  public void setConnectorBindingId(String connectorBindingId) {
    this.connectorBindingId = connectorBindingId;
  }
   
}
TOP

Related Classes of org.teiid.query.processor.relational.AccessNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.