예제 #1
0
  /**
   * Convert a list of SingleElementSymbols to a List of ColumnInfo objects.
   *
   * @param symbols List of SingleElementSymbols
   * @return List of ColumnInfos
   */
  public static List createColumnInfos(List symbols) {
    List infos = new ArrayList(symbols.size());
    Iterator iter = symbols.iterator();
    while (iter.hasNext()) {
      Expression symbol = (Expression) iter.next();
      String name = Symbol.getName(symbol);
      if (symbol instanceof AliasSymbol) {
        AliasSymbol alias = (AliasSymbol) symbol;
        symbol = alias.getSymbol();
      }
      if (symbol instanceof ElementSymbol) {
        ElementSymbol element = (ElementSymbol) symbol;
        GroupSymbol group = element.getGroupSymbol();
        Object groupID = null;
        if (group != null) {
          groupID = group.getMetadataID();
        }
        infos.add(
            new ColumnInfo(
                name,
                DataTypeManager.getDataTypeName(element.getType()),
                element.getType(),
                groupID,
                element.getMetadataID()));
      } else { // ExpressionSymbol or AggregateSymbol
        // Expressions don't map to a single element or group, so don't save that info
        infos.add(
            new ColumnInfo(
                name, DataTypeManager.getDataTypeName(symbol.getType()), symbol.getType()));
      }
    }

    return infos;
  }
 public static void determineDependencies(AbstractMetadataRecord p, Command command) {
   Collection<GroupSymbol> groups =
       GroupCollectorVisitor.getGroupsIgnoreInlineViewsAndEvaluatableSubqueries(command, true);
   LinkedHashSet<AbstractMetadataRecord> values = new LinkedHashSet<AbstractMetadataRecord>();
   for (GroupSymbol group : groups) {
     Object mid = group.getMetadataID();
     if (mid instanceof TempMetadataAdapter) {
       mid = ((TempMetadataID) mid).getOriginalMetadataID();
     }
     if (mid instanceof AbstractMetadataRecord) {
       values.add((AbstractMetadataRecord) mid);
     }
   }
   Collection<ElementSymbol> elems = ElementCollectorVisitor.getElements(command, true, true);
   for (ElementSymbol elem : elems) {
     Object mid = elem.getMetadataID();
     if (mid instanceof TempMetadataAdapter) {
       mid = ((TempMetadataID) mid).getOriginalMetadataID();
     }
     if (mid instanceof AbstractMetadataRecord) {
       values.add((AbstractMetadataRecord) mid);
     }
   }
   p.setIncomingObjects(new ArrayList<AbstractMetadataRecord>(values));
 }
예제 #3
0
  private RelationalNode correctProjectionInternalTables(PlanNode node, AccessNode aNode)
      throws QueryMetadataException, TeiidComponentException {
    if (node.getGroups().size() != 1) {
      return aNode;
    }
    GroupSymbol group = node.getGroups().iterator().next();
    if (!CoreConstants.SYSTEM_MODEL.equals(
            metadata.getFullName(metadata.getModelID(group.getMetadataID())))
        && !CoreConstants.SYSTEM_ADMIN_MODEL.equals(
            metadata.getFullName(metadata.getModelID(group.getMetadataID())))) {
      return aNode;
    }
    List projectSymbols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
    List<ElementSymbol> acutalColumns = ResolverUtil.resolveElementsInGroup(group, metadata);
    if (projectSymbols.equals(acutalColumns)) {
      return aNode;
    }
    node.setProperty(NodeConstants.Info.OUTPUT_COLS, acutalColumns);
    if (node.getParent() != null && node.getParent().getType() == NodeConstants.Types.PROJECT) {
      // if the parent is already a project, just correcting the output cols is enough
      return aNode;
    }
    ProjectNode pnode = new ProjectNode(getID());

    pnode.setSelectSymbols(projectSymbols);
    aNode = (AccessNode) prepareToAdd(node, aNode);
    node.setProperty(NodeConstants.Info.OUTPUT_COLS, projectSymbols);
    pnode.addChild(aNode);
    return pnode;
  }
예제 #4
0
  private void setRoutingName(AccessNode accessNode, PlanNode node, Command command)
      throws QueryPlannerException, TeiidComponentException {

    // Look up connector binding name
    try {
      Object modelID = node.getProperty(NodeConstants.Info.MODEL_ID);
      if (modelID == null || modelID instanceof TempMetadataID) {
        if (command instanceof StoredProcedure) {
          modelID = ((StoredProcedure) command).getModelID();
        } else if (!(command instanceof Create || command instanceof Drop)) {
          Collection<GroupSymbol> groups = GroupCollectorVisitor.getGroups(command, true);
          GroupSymbol group = groups.iterator().next();

          modelID = metadata.getModelID(group.getMetadataID());
        }
      }
      String cbName = metadata.getFullName(modelID);
      accessNode.setModelName(cbName);
      accessNode.setModelId(modelID);
      accessNode.setConformedTo((Set<Object>) node.getProperty(Info.CONFORMED_SOURCES));
    } catch (QueryMetadataException e) {
      throw new QueryPlannerException(
          QueryPlugin.Event.TEIID30251, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30251));
    }
  }
예제 #5
0
 TempTable getOrCreateTempTable(
     String tempTableID,
     Command command,
     BufferManager buffer,
     boolean delegate,
     boolean forUpdate,
     CommandContext context)
     throws TeiidProcessingException, BlockedException, TeiidComponentException {
   TempTable tempTable = getTempTable(tempTableID, command, buffer, delegate, forUpdate, context);
   if (tempTable != null) {
     if (processors != null) {
       TableProcessor withProcessor = processors.get(tempTableID);
       if (withProcessor != null) {
         buildWithTable(tempTableID, withProcessor, tempTable);
       }
     }
     return tempTable;
   }
   // allow implicit temp group definition
   List<ElementSymbol> columns = null;
   if (command instanceof Insert) {
     Insert insert = (Insert) command;
     GroupSymbol group = insert.getGroup();
     if (group.isImplicitTempGroupSymbol()) {
       columns = insert.getVariables();
     }
   }
   if (columns == null) {
     if (processors != null) {
       TableProcessor withProcessor = processors.get(tempTableID);
       if (withProcessor != null) {
         LogManager.logDetail(
             LogConstants.CTX_DQP,
             "Creating temporary table for with clause",
             tempTableID); //$NON-NLS-1$
         Create create = new Create();
         create.setTable(new GroupSymbol(tempTableID));
         create.setElementSymbolsAsColumns(withProcessor.columns);
         tempTable = addTempTable(tempTableID, create, buffer, true, context);
         buildWithTable(tempTableID, withProcessor, tempTable);
         return tempTable;
       }
     }
     throw new QueryProcessingException(
         QueryPlugin.Event.TEIID30226,
         QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30226, tempTableID));
   }
   LogManager.logDetail(
       LogConstants.CTX_DQP, "Creating temporary table", tempTableID); // $NON-NLS-1$
   Create create = new Create();
   create.setTable(new GroupSymbol(tempTableID));
   create.setElementSymbolsAsColumns(columns);
   return addTempTable(tempTableID, create, buffer, true, context);
 }
예제 #6
0
 private void collectDeclareVariable(
     DeclareStatement obj,
     GroupSymbol variables,
     TempMetadataAdapter metadata,
     GroupContext externalGroups)
     throws QueryResolverException, TeiidComponentException {
   ElementSymbol variable = obj.getVariable();
   String typeName = obj.getVariableType();
   GroupSymbol gs = variable.getGroupSymbol();
   if (gs == null) {
     String outputName = variable.getShortName();
     variable.setGroupSymbol(new GroupSymbol(ProcedureReservedWords.VARIABLES));
     variable.setOutputName(outputName);
   } else {
     if (gs.getSchema() != null
         || !gs.getShortName().equalsIgnoreCase(ProcedureReservedWords.VARIABLES)) {
       handleUnresolvableDeclaration(
           variable,
           QueryPlugin.Util.getString(
               "ERR.015.010.0031",
               new Object[] {ProcedureReservedWords.VARIABLES, variable})); // $NON-NLS-1$
     }
   }
   boolean exists = false;
   try {
     ResolverVisitor.resolveLanguageObject(variable, null, externalGroups, metadata);
     exists = true;
   } catch (QueryResolverException e) {
     // ignore, not already defined
   }
   if (exists) {
     handleUnresolvableDeclaration(
         variable,
         QueryPlugin.Util.getString("ERR.015.010.0032", variable.getOutputName())); // $NON-NLS-1$
   }
   variable.setType(DataTypeManager.getDataTypeClass(typeName));
   variable.setGroupSymbol(variables);
   TempMetadataID id =
       new TempMetadataID(
           variable.getName(),
           typeName.equalsIgnoreCase(SQLConstants.NonReserved.EXCEPTION)
               ? Exception.class
               : variable.getType());
   id.setUpdatable(true);
   variable.setMetadataID(id);
   // TODO: this will cause the variables group to loose it's cache of resolved symbols
   metadata
       .getMetadataStore()
       .addElementToTempGroup(ProcedureReservedWords.VARIABLES, variable.clone());
 }
예제 #7
0
  public PlanNode getDescriptionProperties() {
    PlanNode props = super.getDescriptionProperties();
    props.addProperty(PROP_INTO_GROUP, intoGroup.toString());
    List<String> selectCols = new ArrayList<String>(intoElements.size());
    for (int i = 0; i < this.intoElements.size(); i++) {
      selectCols.add(this.intoElements.get(i).toString());
    }
    props.addProperty(PROP_SELECT_COLS, selectCols);

    return props;
  }
예제 #8
0
  /**
   * @see org.teiid.query.resolver.CommandResolver#resolveCommand(org.teiid.query.sql.lang.Command,
   *     TempMetadataAdapter, boolean)
   */
  @Override
  public void resolveCommand(
      Command command, TempMetadataAdapter metadata, boolean resolveNullLiterals) throws Exception {

    DynamicCommand dynamicCmd = (DynamicCommand) command;

    Iterator columns = dynamicCmd.getAsColumns().iterator();

    Set<GroupSymbol> groups = new HashSet<GroupSymbol>();

    // if there is no into group, just create temp metadata ids
    if (dynamicCmd.getIntoGroup() == null) {
      while (columns.hasNext()) {
        ElementSymbol column = (ElementSymbol) columns.next();
        column.setMetadataID(new TempMetadataID(column.getShortName(), column.getType()));
      }
    } else if (dynamicCmd.getIntoGroup().isTempGroupSymbol()) {
      while (columns.hasNext()) {
        ElementSymbol column = (ElementSymbol) columns.next();
        GroupSymbol gs = getTeiidParser().createASTNode(ASTNodes.GROUP_SYMBOL);
        gs.setName(dynamicCmd.getIntoGroup().getName());
        column.setGroupSymbol(gs);
      }
    }

    ResolverVisitor visitor = new ResolverVisitor(getTeiidParser().getVersion());
    visitor.resolveLanguageObject(
        dynamicCmd, groups, dynamicCmd.getExternalGroupContexts(), metadata);
    String sqlType = getDataTypeManager().getDataTypeName(dynamicCmd.getSql().getType());
    String targetType = DataTypeManagerService.DefaultDataTypes.STRING.getId();

    if (!targetType.equals(sqlType)
        && !getDataTypeManager().isImplicitConversion(sqlType, targetType)) {
      throw new QueryResolverException(Messages.gs(Messages.TEIID.TEIID30100, sqlType));
    }

    if (dynamicCmd.getUsing() != null && !dynamicCmd.getUsing().isEmpty()) {
      for (SetClause clause : dynamicCmd.getUsing().getClauses()) {
        ElementSymbol id = clause.getSymbol();
        GroupSymbol gs = getTeiidParser().createASTNode(ASTNodes.GROUP_SYMBOL);
        gs.setName(ProcedureReservedWords.DVARS);
        id.setGroupSymbol(gs);
        id.setType(clause.getValue().getType());
        id.setMetadataID(new TempMetadataID(id.getName(), id.getType()));
      }
    }

    GroupSymbol intoSymbol = dynamicCmd.getIntoGroup();
    if (intoSymbol != null) {
      if (!intoSymbol.isImplicitTempGroupSymbol()) {
        ResolverUtil.resolveGroup(intoSymbol, metadata);
      } else {
        List symbols = dynamicCmd.getAsColumns();
        ResolverUtil.resolveImplicitTempGroup(metadata, intoSymbol, symbols);
      }
    }
  }
예제 #9
0
  private void isValidGroup(TempMetadataAdapter metadata, String groupName)
      throws QueryResolverException {
    if (metadata.getMetadataStore().getTempGroupID(groupName) != null) {
      throw new QueryResolverException(
          QueryPlugin.Event.TEIID30124,
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30124, groupName));
    }

    // check - cursor name should not start with #
    if (GroupSymbol.isTempGroupName(groupName)) {
      throw new QueryResolverException(
          QueryPlugin.Event.TEIID30125,
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30125, groupName));
    }
  }
예제 #10
0
파일: Insert.java 프로젝트: skethire/teiid
  /**
   * Return a deep copy of this Insert.
   *
   * @return Deep copy of Insert
   */
  public Object clone() {
    GroupSymbol copyGroup = null;
    if (group != null) {
      copyGroup = group.clone();
    }

    List<ElementSymbol> copyVars =
        LanguageObject.Util.deepClone(getVariables(), ElementSymbol.class);

    List<Expression> copyVals = null;

    if (getValues() != null) {
      copyVals = LanguageObject.Util.deepClone(getValues(), Expression.class);
    }

    Insert copy = new Insert(copyGroup, copyVars, copyVals);
    if (this.queryExpression != null) {
      copy.setQueryExpression((QueryCommand) this.queryExpression.clone());
    }
    this.copyMetadataState(copy);
    return copy;
  }
예제 #11
0
 TempTable getOrCreateTempTable(
     String tempTableID,
     Command command,
     BufferManager buffer,
     boolean delegate,
     boolean forUpdate,
     CommandContext context,
     GroupSymbol group)
     throws TeiidProcessingException, BlockedException, TeiidComponentException {
   if (!(group.getMetadataID() instanceof TempMetadataID)) {
     // TODO: use a proper metadata
     TempTableStore tts = context.getSessionTempTableStore();
     context.setDeterminismLevel(Determinism.SESSION_DETERMINISTIC);
     if (tts.getTempTable(tempTableID) == null) {
       // implicitly create global (session scoped) temp table
       LogManager.logDetail(
           LogConstants.CTX_DQP, "binding global temp table to session", group); // $NON-NLS-1$
       QueryMetadataInterface metadata = context.getMetadata();
       Create create = GlobalTableStoreImpl.getCreateCommand(group, false, metadata);
       tts.addTempTable(tempTableID, create, buffer, true, context);
     }
     return getTempTable(tempTableID, command, buffer, delegate, forUpdate, context);
   }
   TempTable tempTable = getTempTable(tempTableID, command, buffer, delegate, forUpdate, context);
   if (tempTable != null) {
     if (processors != null) {
       TableProcessor withProcessor = processors.get(tempTableID);
       if (withProcessor != null) {
         TempTable tt = withProcessor.process(tempTable);
         if (tt != tempTable) {
           return tt;
         }
         processors.remove(tempTableID);
       }
     }
     return tempTable;
   }
   // allow implicit temp group definition
   List<ElementSymbol> columns = null;
   if (command instanceof Insert) {
     Insert insert = (Insert) command;
     if (group.isImplicitTempGroupSymbol()) {
       columns = insert.getVariables();
     }
   }
   if (columns == null) {
     if (processors != null) {
       TableProcessor withProcessor = processors.get(tempTableID);
       if (withProcessor != null) {
         LogManager.logDetail(
             LogConstants.CTX_DQP,
             "Creating temporary table for with clause",
             tempTableID); //$NON-NLS-1$
         Create create = new Create();
         create.setTable(new GroupSymbol(tempTableID));
         create.setElementSymbolsAsColumns(withProcessor.columns);
         withProcessor.alterCreate(create);
         tempTable = addTempTable(tempTableID, create, buffer, true, context);
         TempTable tt = withProcessor.process(tempTable);
         if (tt != tempTable) {
           return tt;
         }
         processors.remove(tempTableID);
         return tempTable;
       }
     }
     if (delegate && this.parentTempTableStore != null) {
       // may be a cte from a higher scope that needs to have creation triggered
       return parentTempTableStore.getOrCreateTempTable(
           tempTableID, command, buffer, delegate, forUpdate, context, group);
     }
     throw new QueryProcessingException(
         QueryPlugin.Event.TEIID30226,
         QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30226, tempTableID));
   }
   LogManager.logDetail(
       LogConstants.CTX_DQP, "Creating temporary table", tempTableID); // $NON-NLS-1$
   Create create = new Create();
   create.setTable(new GroupSymbol(tempTableID));
   create.setElementSymbolsAsColumns(columns);
   return addTempTable(tempTableID, create, buffer, true, context);
 }
예제 #12
0
  private TupleSource handleSystemProcedures(final CommandContext context, StoredProcedure proc)
      throws TeiidComponentException, QueryMetadataException, QueryProcessingException,
          QueryResolverException, QueryValidatorException, TeiidProcessingException,
          ExpressionEvaluationException {
    final QueryMetadataInterface metadata = context.getMetadata();
    if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEW)) {
      Object groupID =
          validateMatView(
              metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue());
      TempMetadataID matTableId =
          context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID);
      final GlobalTableStore globalStore = getGlobalStore(context, matTableId);
      String matViewName = metadata.getFullName(groupID);
      String matTableName = metadata.getFullName(matTableId);
      LogManager.logDetail(
          LogConstants.CTX_MATVIEWS, "processing refreshmatview for", matViewName); // $NON-NLS-1$
      boolean invalidate =
          Boolean.TRUE.equals(((Constant) proc.getParameter(3).getExpression()).getValue());
      boolean needsLoading =
          globalStore.needsLoading(matTableName, globalStore.getAddress(), true, true, invalidate);
      if (!needsLoading) {
        return CollectionTupleSource.createUpdateCountTupleSource(-1);
      }
      GroupSymbol matTable = new GroupSymbol(matTableName);
      matTable.setMetadataID(matTableId);
      return loadGlobalTable(context, matTable, matTableName, globalStore);
    } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROWS)) {
      final Object groupID =
          validateMatView(
              metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue());
      TempMetadataID matTableId =
          context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID);
      final GlobalTableStore globalStore = getGlobalStore(context, matTableId);
      Object pk = metadata.getPrimaryKey(groupID);
      String matViewName = metadata.getFullName(groupID);
      if (pk == null) {
        throw new QueryProcessingException(
            QueryPlugin.Event.TEIID30230,
            QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName));
      }
      List<?> ids = metadata.getElementIDsInKey(pk);
      Object[][] params =
          (Object[][])
              ((ArrayImpl) ((Constant) proc.getParameter(3).getExpression()).getValue())
                  .getValues();
      return updateMatviewRows(context, metadata, groupID, globalStore, matViewName, ids, params);
    } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROW)) {
      final Object groupID =
          validateMatView(
              metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue());
      TempMetadataID matTableId =
          context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID);
      final GlobalTableStore globalStore = getGlobalStore(context, matTableId);
      Object pk = metadata.getPrimaryKey(groupID);
      final String matViewName = metadata.getFullName(groupID);
      if (pk == null) {
        throw new QueryProcessingException(
            QueryPlugin.Event.TEIID30230,
            QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName));
      }
      List<?> ids = metadata.getElementIDsInKey(pk);
      Constant key = (Constant) proc.getParameter(3).getExpression();
      Object initialValue = key.getValue();
      SPParameter keyOther = proc.getParameter(4);
      Object[] param = null;
      if (keyOther != null) {
        Object[] otherCols =
            ((ArrayImpl) ((Constant) keyOther.getExpression()).getValue()).getValues();
        if (otherCols != null) {
          param = new Object[1 + otherCols.length];
          param[0] = initialValue;
          for (int i = 0; i < otherCols.length; i++) {
            param[i + 1] = otherCols[i];
          }
        }
      }
      if (param == null) {
        param = new Object[] {initialValue};
      }

      Object[][] params = new Object[][] {param};

      return updateMatviewRows(context, metadata, groupID, globalStore, matViewName, ids, params);
    }
    return null;
  }
예제 #13
0
  protected RelationalNode convertNode(PlanNode node)
      throws TeiidComponentException, TeiidProcessingException {

    RelationalNode processNode = null;

    switch (node.getType()) {
      case NodeConstants.Types.PROJECT:
        GroupSymbol intoGroup = (GroupSymbol) node.getProperty(NodeConstants.Info.INTO_GROUP);
        if (intoGroup != null) {
          try {
            Insert insert = (Insert) node.getFirstChild().getProperty(Info.VIRTUAL_COMMAND);
            List<ElementSymbol> allIntoElements = insert.getVariables();

            Object groupID = intoGroup.getMetadataID();
            Object modelID = metadata.getModelID(groupID);
            String modelName = metadata.getFullName(modelID);
            if (metadata.isVirtualGroup(groupID)) {
              InsertPlanExecutionNode ipen = new InsertPlanExecutionNode(getID(), metadata);
              ipen.setProcessorPlan(
                  (ProcessorPlan) node.getFirstChild().getProperty(Info.PROCESSOR_PLAN));
              ipen.setReferences(insert.getValues());
              processNode = ipen;
            } else {
              ProjectIntoNode pinode = new ProjectIntoNode(getID());
              pinode.setIntoGroup(intoGroup);
              pinode.setIntoElements(allIntoElements);
              pinode.setModelName(modelName);
              pinode.setConstraint((Criteria) node.getProperty(Info.CONSTRAINT));
              processNode = pinode;
              SourceCapabilities caps = capFinder.findCapabilities(modelName);
              if (caps.supportsCapability(Capability.INSERT_WITH_ITERATOR)) {
                pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.ITERATOR);
              } else if (caps.supportsCapability(Capability.BATCHED_UPDATES)) {
                pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.BATCH);
              } else {
                pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.SINGLE);
              }
            }
          } catch (QueryMetadataException e) {
            throw new TeiidComponentException(QueryPlugin.Event.TEIID30247, e);
          }

        } else {
          List<Expression> symbols = (List) node.getProperty(NodeConstants.Info.PROJECT_COLS);

          ProjectNode pnode = new ProjectNode(getID());
          pnode.setSelectSymbols(symbols);
          processNode = pnode;

          if (node.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) {
            WindowFunctionProjectNode wfpn = new WindowFunctionProjectNode(getID());

            // with partial projection the window function may already be pushed, we'll check for
            // that here
            ArrayList<Expression> filtered = new ArrayList<Expression>();
            List<Expression> childSymbols =
                (List) node.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS);
            for (Expression ex : symbols) {
              ex = SymbolMap.getExpression(ex);
              if (childSymbols.contains(ex)) {
                continue;
              }
              filtered.add(ex);
            }
            Set<WindowFunction> windowFunctions =
                RuleAssignOutputElements.getWindowFunctions(filtered);
            if (!windowFunctions.isEmpty()) {
              // TODO: check for selecting all window functions
              List<Expression> outputElements = new ArrayList<Expression>(windowFunctions);
              // collect the other projected expressions
              for (Expression singleElementSymbol :
                  (List<Expression>) node.getFirstChild().getProperty(Info.OUTPUT_COLS)) {
                outputElements.add(singleElementSymbol);
              }
              wfpn.setElements(outputElements);
              wfpn.init();
              pnode.addChild(wfpn);
            }
          }
        }
        break;

      case NodeConstants.Types.JOIN:
        JoinType jtype = (JoinType) node.getProperty(NodeConstants.Info.JOIN_TYPE);
        JoinStrategyType stype =
            (JoinStrategyType) node.getProperty(NodeConstants.Info.JOIN_STRATEGY);

        JoinNode jnode = new JoinNode(getID());
        jnode.setJoinType(jtype);
        jnode.setLeftDistinct(node.hasBooleanProperty(NodeConstants.Info.IS_LEFT_DISTINCT));
        jnode.setRightDistinct(node.hasBooleanProperty(NodeConstants.Info.IS_RIGHT_DISTINCT));
        List joinCrits = (List) node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
        String depValueSource =
            (String) node.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE);
        SortOption leftSort = (SortOption) node.getProperty(NodeConstants.Info.SORT_LEFT);
        if (stype == JoinStrategyType.MERGE || stype == JoinStrategyType.ENHANCED_SORT) {
          MergeJoinStrategy mjStrategy = null;
          if (stype.equals(JoinStrategyType.ENHANCED_SORT)) {
            EnhancedSortMergeJoinStrategy esmjStrategy =
                new EnhancedSortMergeJoinStrategy(
                    leftSort, (SortOption) node.getProperty(NodeConstants.Info.SORT_RIGHT));
            esmjStrategy.setSemiDep(node.hasBooleanProperty(Info.IS_SEMI_DEP));
            mjStrategy = esmjStrategy;
          } else {
            mjStrategy =
                new MergeJoinStrategy(
                    leftSort, (SortOption) node.getProperty(NodeConstants.Info.SORT_RIGHT), false);
          }
          jnode.setJoinStrategy(mjStrategy);
          List leftExpressions = (List) node.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS);
          List rightExpressions = (List) node.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS);
          jnode.setJoinExpressions(leftExpressions, rightExpressions);
          joinCrits = (List) node.getProperty(NodeConstants.Info.NON_EQUI_JOIN_CRITERIA);
        } else if (stype == JoinStrategyType.NESTED_TABLE) {
          NestedTableJoinStrategy ntjStrategy = new NestedTableJoinStrategy();
          jnode.setJoinStrategy(ntjStrategy);
          SymbolMap references = (SymbolMap) node.getProperty(Info.LEFT_NESTED_REFERENCES);
          ntjStrategy.setLeftMap(references);
          references = (SymbolMap) node.getProperty(Info.RIGHT_NESTED_REFERENCES);
          ntjStrategy.setRightMap(references);
        } else {
          NestedLoopJoinStrategy nljStrategy = new NestedLoopJoinStrategy();
          jnode.setJoinStrategy(nljStrategy);
        }
        Criteria joinCrit = Criteria.combineCriteria(joinCrits);
        jnode.setJoinCriteria(joinCrit);

        processNode = jnode;

        jnode.setDependentValueSource(depValueSource);

        break;

      case NodeConstants.Types.ACCESS:
        ProcessorPlan plan = (ProcessorPlan) node.getProperty(NodeConstants.Info.PROCESSOR_PLAN);
        if (plan != null) {

          PlanExecutionNode peNode = null;

          Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.PROCEDURE_CRITERIA);

          if (crit != null) {
            List references = (List) node.getProperty(NodeConstants.Info.PROCEDURE_INPUTS);
            List defaults = (List) node.getProperty(NodeConstants.Info.PROCEDURE_DEFAULTS);

            peNode = new DependentProcedureExecutionNode(getID(), crit, references, defaults);
          } else {
            peNode = new PlanExecutionNode(getID());
          }

          peNode.setProcessorPlan(plan);
          processNode = peNode;

        } else {
          AccessNode aNode = null;
          Command command = (Command) node.getProperty(NodeConstants.Info.ATOMIC_REQUEST);
          Object modelID = node.getProperty(NodeConstants.Info.MODEL_ID);
          if (modelID != null) {
            String fullName = metadata.getFullName(modelID);
            if (!capFinder.isValid(fullName)) {
              // TODO: we ideally want to handle the partial resutls case here differently
              //      by adding a null node / and a source warning
              //      for now it's just as easy to say that the user needs to take steps to
              //      return static capabilities
              SourceCapabilities caps = capFinder.findCapabilities(fullName);
              Exception cause = null;
              if (caps != null) {
                cause = (Exception) caps.getSourceProperty(Capability.INVALID_EXCEPTION);
              }
              throw new QueryPlannerException(
                  QueryPlugin.Event.TEIID30498,
                  cause,
                  QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30498, fullName));
            }
          }
          EvaluatableVisitor ev = null;
          if (node.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
            if (command instanceof StoredProcedure) {
              List references = (List) node.getProperty(NodeConstants.Info.PROCEDURE_INPUTS);
              List defaults = (List) node.getProperty(NodeConstants.Info.PROCEDURE_DEFAULTS);
              Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.PROCEDURE_CRITERIA);

              DependentProcedureAccessNode depAccessNode =
                  new DependentProcedureAccessNode(getID(), crit, references, defaults);
              processNode = depAccessNode;
              aNode = depAccessNode;
            } else {
              // create dependent access node
              DependentAccessNode depAccessNode = new DependentAccessNode(getID());

              if (modelID != null) {
                depAccessNode.setPushdown(
                    CapabilitiesUtil.supports(
                        Capability.DEPENDENT_JOIN, modelID, metadata, capFinder));
                depAccessNode.setMaxSetSize(
                    CapabilitiesUtil.getMaxInCriteriaSize(modelID, metadata, capFinder));
                depAccessNode.setMaxPredicates(
                    CapabilitiesUtil.getMaxDependentPredicates(modelID, metadata, capFinder));
                depAccessNode.setUseBindings(
                    CapabilitiesUtil.supports(
                        Capability.DEPENDENT_JOIN_BINDINGS, modelID, metadata, capFinder));
                // TODO: allow the translator to drive this property
                // simplistic check of whether this query is complex to re-execute
                Query query = (Query) command;
                if (query.getGroupBy() != null
                    || query.getFrom().getClauses().size() > 1
                    || !(query.getFrom().getClauses().get(0) instanceof UnaryFromClause)
                    || query.getWith() != null) {
                  depAccessNode.setComplexQuery(true);
                } else {
                  // check to see if there in an index on at least one of the dependent sets
                  Set<GroupSymbol> groups = new HashSet<GroupSymbol>(query.getFrom().getGroups());
                  boolean found = false;
                  for (Criteria crit : Criteria.separateCriteriaByAnd(query.getCriteria())) {
                    if (crit instanceof DependentSetCriteria) {
                      DependentSetCriteria dsc = (DependentSetCriteria) crit;
                      if (NewCalculateCostUtil.getKeyUsed(
                              ElementCollectorVisitor.getElements(dsc.getExpression(), true),
                              groups,
                              metadata,
                              null)
                          != null) {
                        found = true;
                        break;
                      }
                    }
                  }
                  if (!found) {
                    depAccessNode.setComplexQuery(true);
                  }
                }
              }
              processNode = depAccessNode;
              aNode = depAccessNode;
            }
            aNode.setShouldEvaluateExpressions(true);
          } else {

            // create access node
            aNode = new AccessNode(getID());
            processNode = aNode;
          }
          // -- special handling for system tables. currently they cannot perform projection
          try {
            if (command instanceof Query) {
              processNode = correctProjectionInternalTables(node, aNode);
            }
          } catch (QueryMetadataException err) {
            throw new TeiidComponentException(QueryPlugin.Event.TEIID30248, err);
          }
          setRoutingName(aNode, node, command);
          boolean shouldEval = false;
          if (command instanceof Insert) {
            Insert insert = (Insert) command;
            if (insert.getQueryExpression() != null) {
              insert.setQueryExpression(
                  (QueryCommand) aliasCommand(aNode, insert.getQueryExpression(), modelID));
            } else {
              for (int i = 0; i < insert.getValues().size(); i++) {
                Expression ex = (Expression) insert.getValues().get(i);
                if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject(
                    ex, modelID, metadata, capFinder, analysisRecord)) {
                  // replace with an expression symbol to let the rewriter know that it should be
                  // replaced
                  insert.getValues().set(i, new ExpressionSymbol("x", ex));
                  shouldEval = true;
                }
              }
            }
          } else if (command instanceof QueryCommand) {
            command = aliasCommand(aNode, command, modelID);
          }
          ev = EvaluatableVisitor.needsEvaluation(command, modelID, metadata, capFinder);
          aNode.setShouldEvaluateExpressions(
              ev.requiresEvaluation(EvaluationLevel.PROCESSING) || shouldEval);
          aNode.setCommand(command);
          Map<GroupSymbol, PlanNode> subPlans =
              (Map<GroupSymbol, PlanNode>) node.getProperty(Info.SUB_PLANS);

          // it makes more sense to allow the multisource affect to be elevated above just access
          // nodes
          if (aNode.getModelId() != null && metadata.isMultiSource(aNode.getModelId())) {
            VDBMetaData vdb = context.getVdb();
            aNode.setShouldEvaluateExpressions(true); // forces a rewrite
            aNode.setElements((List) node.getProperty(NodeConstants.Info.OUTPUT_COLS));
            if (node.hasBooleanProperty(Info.IS_MULTI_SOURCE)) {
              Expression ex = rewriteMultiSourceCommand(aNode.getCommand());
              aNode.setConnectorBindingExpression(ex);
              aNode.setMultiSource(true);
            } else {
              String sourceName = (String) node.getProperty(Info.SOURCE_NAME);
              aNode.setConnectorBindingExpression(new Constant(sourceName));
            }
          } else if (subPlans == null) {
            if (!aNode.isShouldEvaluate()) {
              aNode.minimizeProject(command);
            }
            // check if valid to share this with other nodes
            if (ev != null
                && ev.getDeterminismLevel().compareTo(Determinism.COMMAND_DETERMINISTIC) >= 0
                && command.areResultsCachable()) {
              checkForSharedSourceCommand(aNode);
            }
          }
          if (subPlans != null) {
            QueryCommand qc = (QueryCommand) command;
            if (qc.getWith() == null) {
              qc.setWith(new ArrayList<WithQueryCommand>(subPlans.size()));
            }
            Map<GroupSymbol, RelationalPlan> plans =
                new LinkedHashMap<GroupSymbol, RelationalPlan>();
            for (Map.Entry<GroupSymbol, PlanNode> entry : subPlans.entrySet()) {
              RelationalPlan subPlan = convert(entry.getValue());
              List<ElementSymbol> elems =
                  ResolverUtil.resolveElementsInGroup(entry.getKey(), metadata);
              subPlan.setOutputElements(elems);
              plans.put(entry.getKey(), subPlan);
              WithQueryCommand withQueryCommand = new WithQueryCommand(entry.getKey(), elems, null);
              qc.getWith().add(withQueryCommand);
            }
            aNode.setSubPlans(plans);
          }
        }
        break;

      case NodeConstants.Types.SELECT:
        Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
        if (!node.hasCollectionProperty(Info.OUTPUT_COLS)) {
          // the late optimization to create a dependent join from a subquery introduces
          // criteria that have no output elements set
          // TODO that should be cleaner, but the logic currently expects to be run after join
          // implementation
          // and rerunning assign output elements seems excessive
          node.setProperty(Info.OUTPUT_COLS, node.getFirstChild().getProperty(Info.OUTPUT_COLS));
        }
        SelectNode selnode = new SelectNode(getID());
        selnode.setCriteria(crit);
        // in case the parent was a source
        selnode.setProjectedExpressions(
            (List<Expression>) node.getProperty(NodeConstants.Info.PROJECT_COLS));
        processNode = selnode;

        break;

      case NodeConstants.Types.SORT:
      case NodeConstants.Types.DUP_REMOVE:
        if (node.getType() == NodeConstants.Types.DUP_REMOVE) {
          processNode = new DupRemoveNode(getID());
        } else {
          SortNode sortNode = new SortNode(getID());
          OrderBy orderBy = (OrderBy) node.getProperty(NodeConstants.Info.SORT_ORDER);
          if (orderBy != null) {
            sortNode.setSortElements(orderBy.getOrderByItems());
          }
          if (node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL)) {
            sortNode.setMode(Mode.DUP_REMOVE_SORT);
          }

          processNode = sortNode;
        }
        break;
      case NodeConstants.Types.GROUP:
        GroupingNode gnode = new GroupingNode(getID());
        gnode.setRollup(node.hasBooleanProperty(Info.ROLLUP));
        SymbolMap groupingMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP);
        gnode.setOutputMapping(groupingMap);
        gnode.setRemoveDuplicates(node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL));
        List<Expression> gCols = (List) node.getProperty(NodeConstants.Info.GROUP_COLS);
        OrderBy orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER);
        if (orderBy == null) {
          if (gCols != null) {
            LinkedHashSet<Expression> exprs = new LinkedHashSet<Expression>();
            for (Expression ex : gCols) {
              exprs.add(SymbolMap.getExpression(ex));
            }
            orderBy =
                new OrderBy(
                    RuleChooseJoinStrategy.createExpressionSymbols(
                        new ArrayList<Expression>(exprs)));
          }
        } else {
          HashSet<Expression> seen = new HashSet<Expression>();
          for (int i = 0; i < gCols.size(); i++) {
            if (i < orderBy.getOrderByItems().size()) {
              OrderByItem orderByItem = orderBy.getOrderByItems().get(i);
              Expression ex = SymbolMap.getExpression(orderByItem.getSymbol());
              if (!seen.add(ex)) {
                continue;
              }
              if (ex instanceof ElementSymbol) {
                ex = groupingMap.getMappedExpression((ElementSymbol) ex);
                orderByItem.setSymbol(new ExpressionSymbol("expr", ex)); // $NON-NLS-1$
              }
            } else {
              orderBy.addVariable(
                  new ExpressionSymbol("expr", gCols.get(i)), OrderBy.ASC); // $NON-NLS-1$
            }
          }
        }
        if (orderBy != null) {
          gnode.setOrderBy(orderBy.getOrderByItems());
        }
        processNode = gnode;
        break;

      case NodeConstants.Types.SOURCE:
        Object source = node.getProperty(NodeConstants.Info.TABLE_FUNCTION);
        if (source instanceof XMLTable) {
          XMLTable xt = (XMLTable) source;
          XMLTableNode xtn = new XMLTableNode(getID());
          // we handle the projection filtering once here rather than repeating the
          // path analysis on a per plan basis
          updateGroupName(node, xt);
          Map<Expression, Integer> elementMap =
              RelationalNode.createLookupMap(xt.getProjectedSymbols());
          List cols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
          int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols);
          ArrayList<XMLColumn> filteredColumns = new ArrayList<XMLColumn>(projectionIndexes.length);
          for (int col : projectionIndexes) {
            filteredColumns.add(xt.getColumns().get(col));
          }
          xt.getXQueryExpression().useDocumentProjection(filteredColumns, analysisRecord);
          xtn.setProjectedColumns(filteredColumns);
          xtn.setTable(xt);
          processNode = xtn;
          break;
        }
        if (source instanceof ObjectTable) {
          ObjectTable ot = (ObjectTable) source;
          ObjectTableNode otn = new ObjectTableNode(getID());
          // we handle the projection filtering once here rather than repeating the
          // path analysis on a per plan basis
          updateGroupName(node, ot);
          Map<Expression, Integer> elementMap =
              RelationalNode.createLookupMap(ot.getProjectedSymbols());
          List<Expression> cols =
              (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
          int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols);
          ArrayList<ObjectColumn> filteredColumns =
              new ArrayList<ObjectColumn>(projectionIndexes.length);
          for (int col : projectionIndexes) {
            filteredColumns.add(ot.getColumns().get(col));
          }
          otn.setProjectedColumns(filteredColumns);
          otn.setTable(ot);
          processNode = otn;
          break;
        }
        if (source instanceof TextTable) {
          TextTableNode ttn = new TextTableNode(getID());
          TextTable tt = (TextTable) source;
          updateGroupName(node, tt);
          ttn.setTable(tt);
          processNode = ttn;
          break;
        }
        if (source instanceof ArrayTable) {
          ArrayTableNode atn = new ArrayTableNode(getID());
          ArrayTable at = (ArrayTable) source;
          updateGroupName(node, at);
          atn.setTable(at);
          processNode = atn;
          break;
        }
        SymbolMap symbolMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP);
        if (symbolMap != null) {
          PlanNode child = node.getLastChild();

          if (child.getType() == NodeConstants.Types.PROJECT
              || child.getType() == NodeConstants.Types.SELECT) {
            // update the project cols based upon the original output
            child.setProperty(
                NodeConstants.Info.PROJECT_COLS, child.getProperty(NodeConstants.Info.OUTPUT_COLS));
          }
          child.setProperty(
              NodeConstants.Info.OUTPUT_COLS, node.getProperty(NodeConstants.Info.OUTPUT_COLS));
        }
        return null;
      case NodeConstants.Types.SET_OP:
        Operation setOp = (Operation) node.getProperty(NodeConstants.Info.SET_OPERATION);
        boolean useAll = ((Boolean) node.getProperty(NodeConstants.Info.USE_ALL)).booleanValue();
        if (setOp == Operation.UNION) {
          RelationalNode unionAllNode = new UnionAllNode(getID());

          if (useAll) {
            processNode = unionAllNode;
          } else {
            boolean onlyDupRemoval = node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL);
            if (onlyDupRemoval) {
              processNode = new DupRemoveNode(getID());
            } else {
              SortNode sNode = new SortNode(getID());
              sNode.setMode(Mode.DUP_REMOVE_SORT);
              processNode = sNode;
            }

            unionAllNode.setElements((List) node.getProperty(NodeConstants.Info.OUTPUT_COLS));
            processNode.addChild(unionAllNode);
          }
        } else {
          JoinNode joinAsSet = new JoinNode(getID());
          joinAsSet.setJoinStrategy(
              new MergeJoinStrategy(SortOption.SORT_DISTINCT, SortOption.SORT_DISTINCT, true));
          // If we push these sorts, we will have to enforce null order, since nulls are equal here
          List leftExpressions =
              (List) node.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS);
          List rightExpressions =
              (List) node.getLastChild().getProperty(NodeConstants.Info.OUTPUT_COLS);
          joinAsSet.setJoinType(
              setOp == Operation.EXCEPT ? JoinType.JOIN_ANTI_SEMI : JoinType.JOIN_SEMI);
          joinAsSet.setJoinExpressions(leftExpressions, rightExpressions);
          processNode = joinAsSet;
        }

        break;

      case NodeConstants.Types.TUPLE_LIMIT:
        Expression rowLimit = (Expression) node.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT);
        Expression offset = (Expression) node.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT);
        LimitNode ln = new LimitNode(getID(), rowLimit, offset);
        ln.setImplicit(node.hasBooleanProperty(Info.IS_IMPLICIT_LIMIT));
        processNode = ln;
        break;

      case NodeConstants.Types.NULL:
        processNode = new NullNode(getID());
        break;

      default:
        throw new QueryPlannerException(
            QueryPlugin.Event.TEIID30250,
            QueryPlugin.Util.gs(
                QueryPlugin.Event.TEIID30250, NodeConstants.getNodeTypeString(node.getType())));
    }

    if (processNode != null) {
      processNode = prepareToAdd(node, processNode);
    }

    return processNode;
  }
  private void validate(
      VDBMetaData vdb,
      ModelMetaData model,
      AbstractMetadataRecord record,
      ValidatorReport report,
      IQueryMetadataInterface metadata,
      MetadataFactory mf) {
    ValidatorReport resolverReport = null;
    try {
      if (record instanceof Procedure) {
        Procedure p = (Procedure) record;
        Command command = queryParser.parseProcedure(p.getQueryPlan(), false);
        GroupSymbol gs = createASTNode(ASTNodes.GROUP_SYMBOL);
        gs.setName(p.getFullName());
        QueryResolver resolver = new QueryResolver(queryParser);
        resolver.resolveCommand(command, gs, ICommand.TYPE_STORED_PROCEDURE, metadata, false);
        Validator validator = new Validator();
        resolverReport = validator.validate(command, metadata);
        determineDependencies(p, command);
      } else if (record instanceof Table) {
        Table t = (Table) record;

        GroupSymbol symbol = createASTNode(ASTNodes.GROUP_SYMBOL);
        symbol.setName(t.getFullName());
        ResolverUtil.resolveGroup(symbol, metadata);
        String selectTransformation = t.getSelectTransformation();

        boolean columnsIsEmpty = t.getColumns() == null || t.getColumns().isEmpty();

        // Consider columns if teid 8.11 or lower
        boolean considerColumns_811 =
            isTeiidOrGreater(Version.TEIID_8_12_4) ? true : columnsIsEmpty;
        // Consider columns if teiid 8.12.4+
        boolean considerColumns_8124 =
            isTeiidOrGreater(Version.TEIID_8_12_4) ? columnsIsEmpty : true;

        if (t.isVirtual() && considerColumns_811) {
          QueryCommand command = (QueryCommand) queryParser.parseCommand(selectTransformation);
          QueryResolver resolver = new QueryResolver(queryParser);
          resolver.resolveCommand(command, metadata);
          Validator validator = new Validator();
          resolverReport = validator.validate(command, metadata);

          if (!resolverReport.hasItems() && considerColumns_8124) {
            List<Expression> symbols = command.getProjectedSymbols();
            for (Expression column : symbols) {
              try {
                addColumn(Symbol.getShortName(column), column.getType(), t, mf);
              } catch (Exception e) {
                log(report, model, e.getMessage());
              }
            }
          }

          if (considerColumns_8124) {
            determineDependencies(t, command);
            if (t.getInsertPlan() != null && t.isInsertPlanEnabled()) {
              validateUpdatePlan(
                  model, report, metadata, t, t.getInsertPlan(), Command.TYPE_INSERT);
            }
            if (t.getUpdatePlan() != null && t.isUpdatePlanEnabled()) {
              validateUpdatePlan(
                  model, report, metadata, t, t.getUpdatePlan(), Command.TYPE_UPDATE);
            }
            if (t.getDeletePlan() != null && t.isDeletePlanEnabled()) {
              validateUpdatePlan(
                  model, report, metadata, t, t.getDeletePlan(), Command.TYPE_DELETE);
            }
          }
        }

        boolean addCacheHint = false;
        if (t.isMaterialized() && t.getMaterializedTable() == null) {
          List<KeyRecord> fbis = t.getFunctionBasedIndexes();
          List<GroupSymbol> groups = Arrays.asList(symbol);
          if (fbis != null && !fbis.isEmpty()) {
            for (KeyRecord fbi : fbis) {
              for (int j = 0; j < fbi.getColumns().size(); j++) {
                Column c = fbi.getColumns().get(j);
                if (c.getParent() != fbi) {
                  continue;
                }
                String exprString = c.getNameInSource();
                try {
                  Expression ex = queryParser.parseExpression(exprString);
                  ResolverVisitor resolverVisitor = new ResolverVisitor(teiidVersion);
                  resolverVisitor.resolveLanguageObject(ex, groups, metadata);
                  if (!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(ex)
                      .isEmpty()) {
                    log(
                        report,
                        model,
                        Messages.gs(Messages.TEIID.TEIID31114, exprString, fbi.getFullName()));
                  }
                  EvaluatableVisitor ev = new EvaluatableVisitor(teiidVersion);
                  PreOrPostOrderNavigator.doVisit(ex, ev, PostOrderNavigator.PRE_ORDER);
                  if (ev.getDeterminismLevel().compareTo(Determinism.VDB_DETERMINISTIC) < 0) {
                    log(
                        report,
                        model,
                        Messages.gs(Messages.TEIID.TEIID31115, exprString, fbi.getFullName()));
                  }
                } catch (QueryResolverException e) {
                  log(
                      report,
                      model,
                      Messages.gs(
                          Messages.TEIID.TEIID31116,
                          exprString,
                          fbi.getFullName(),
                          e.getMessage()));
                }
              }
            }
          }
        } else {
          addCacheHint = true;
        }

        // this seems to parse, resolve and validate.
        QueryResolver resolver = new QueryResolver(queryParser);
        QueryNode node =
            resolver.resolveView(
                symbol,
                new QueryNode(t.getSelectTransformation()),
                SQLConstants.Reserved.SELECT,
                metadata);
        CacheHint cacheHint = node.getCommand().getCacheHint();
        Long ttl = -1L;
        if (cacheHint != null
            && cacheHint.getTtl() != null
            && addCacheHint
            && t.getProperty(MATVIEW_TTL, false) == null) {
          ttl = cacheHint.getTtl();
          t.setProperty(MATVIEW_TTL, String.valueOf(ttl));
        }
      }
      if (resolverReport != null && resolverReport.hasItems()) {
        for (ValidatorFailure v : resolverReport.getItems()) {
          log(
              report,
              model,
              v.getStatus() == IValidatorFailure.VFStatus.ERROR ? Severity.ERROR : Severity.WARNING,
              v.getMessage());
        }
      }
      processReport(model, record, report, resolverReport);
    } catch (Exception e) {
      log(
          report,
          model,
          Messages.gs(Messages.TEIID.TEIID31080, record.getFullName(), e.getMessage()));
    }
  }
예제 #15
0
  TupleSource registerRequest(final CommandContext context, String modelName, final Command command)
      throws TeiidComponentException, TeiidProcessingException {
    final TempTableStore contextStore = context.getTempTableStore();
    if (command instanceof Query) {
      Query query = (Query) command;
      if (modelName != null && !modelName.equals(TempMetadataAdapter.TEMP_MODEL.getID())) {
        return null;
      }
      return registerQuery(context, contextStore, query);
    }
    if (command instanceof ProcedureContainer) {
      if (command instanceof StoredProcedure) {
        StoredProcedure proc = (StoredProcedure) command;
        if (CoreConstants.SYSTEM_ADMIN_MODEL.equals(modelName)) {
          TupleSource result = handleSystemProcedures(context, proc);
          if (result != null) {
            return result;
          }
        } else if (proc.getGroup().isGlobalTable()) {
          return handleCachedProcedure(context, proc);
        }
        return null; // it's not a stored procedure we want to handle
      }

      final GroupSymbol group = ((ProcedureContainer) command).getGroup();
      if (!modelName.equals(TempMetadataAdapter.TEMP_MODEL.getID()) || !group.isTempGroupSymbol()) {
        return null;
      }
      return new ProxyTupleSource() {

        @Override
        protected TupleSource createTupleSource()
            throws TeiidComponentException, TeiidProcessingException {
          final String groupKey = group.getNonCorrelationName();
          final TempTable table =
              contextStore.getOrCreateTempTable(
                  groupKey, command, bufferManager, true, true, context, group);
          if (command instanceof Insert) {
            Insert insert = (Insert) command;
            TupleSource ts = insert.getTupleSource();
            if (ts == null) {
              Evaluator eval =
                  new Evaluator(Collections.emptyMap(), TempTableDataManager.this, context);
              List<Object> values = new ArrayList<Object>(insert.getValues().size());
              for (Expression expr : (List<Expression>) insert.getValues()) {
                values.add(eval.evaluate(expr, null));
              }
              ts = new CollectionTupleSource(Arrays.asList(values).iterator());
            }
            return table.insert(ts, insert.getVariables(), true, context);
          }
          if (command instanceof Update) {
            final Update update = (Update) command;
            final Criteria crit = update.getCriteria();
            return table.update(crit, update.getChangeList());
          }
          if (command instanceof Delete) {
            final Delete delete = (Delete) command;
            final Criteria crit = delete.getCriteria();
            if (crit == null) {
              // TODO: we'll add a real truncate later
              int rows = table.truncate(false);
              return CollectionTupleSource.createUpdateCountTupleSource(rows);
            }
            return table.delete(crit);
          }
          throw new AssertionError("unknown command " + command); // $NON-NLS-1$
        }
      };
    }
    if (command instanceof Create) {
      Create create = (Create) command;
      String tempTableName = create.getTable().getName();
      if (contextStore.hasTempTable(tempTableName)) {
        throw new QueryProcessingException(
            QueryPlugin.Event.TEIID30229,
            QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30229, tempTableName));
      }
      if (create.getTableMetadata() != null) {
        contextStore.addForeignTempTable(tempTableName, create);
      } else {
        contextStore.addTempTable(tempTableName, create, bufferManager, true, context);
      }
      return CollectionTupleSource.createUpdateCountTupleSource(0);
    }
    if (command instanceof Drop) {
      String tempTableName = ((Drop) command).getTable().getName();
      contextStore.removeTempTableByName(tempTableName, context);
      return CollectionTupleSource.createUpdateCountTupleSource(0);
    }
    if (command instanceof AlterTempTable) {
      AlterTempTable att = (AlterTempTable) command;
      TempTable tt = contextStore.getTempTable(att.getTempTable());
      Assertion.isNotNull(tt, "Table doesn't exist"); // $NON-NLS-1$
      tt.setUpdatable(false);
      if (att.getIndexColumns() != null && tt.getRowCount() > 2 * tt.getTree().getPageSize(true)) {
        for (List<ElementSymbol> cols : att.getIndexColumns()) {
          tt.addIndex(cols, false);
        }
      }
      return CollectionTupleSource.createUpdateCountTupleSource(0);
    }
    return null;
  }
예제 #16
0
  private TupleSource handleSystemProcedures(final CommandContext context, StoredProcedure proc)
      throws TeiidComponentException, QueryMetadataException, QueryProcessingException,
          QueryResolverException, QueryValidatorException, TeiidProcessingException,
          ExpressionEvaluationException {
    final QueryMetadataInterface metadata = context.getMetadata();
    if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEW)) {
      Object groupID =
          validateMatView(
              metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue());
      TempMetadataID matTableId =
          context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID);
      final GlobalTableStore globalStore = getGlobalStore(context, matTableId);
      String matViewName = metadata.getFullName(groupID);
      String matTableName = metadata.getFullName(matTableId);
      LogManager.logDetail(
          LogConstants.CTX_MATVIEWS, "processing refreshmatview for", matViewName); // $NON-NLS-1$
      boolean invalidate =
          Boolean.TRUE.equals(((Constant) proc.getParameter(3).getExpression()).getValue());
      boolean needsLoading =
          globalStore.needsLoading(matTableName, globalStore.getAddress(), true, true, invalidate);
      if (!needsLoading) {
        return CollectionTupleSource.createUpdateCountTupleSource(-1);
      }
      GroupSymbol matTable = new GroupSymbol(matTableName);
      matTable.setMetadataID(matTableId);
      return loadGlobalTable(context, matTable, matTableName, globalStore);
    } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROW)) {
      final Object groupID =
          validateMatView(
              metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue());
      TempMetadataID matTableId =
          context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID);
      final GlobalTableStore globalStore = getGlobalStore(context, matTableId);
      Object pk = metadata.getPrimaryKey(groupID);
      String matViewName = metadata.getFullName(groupID);
      if (pk == null) {
        throw new QueryProcessingException(
            QueryPlugin.Event.TEIID30230,
            QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName));
      }
      List<?> ids = metadata.getElementIDsInKey(pk);
      Constant key = (Constant) proc.getParameter(3).getExpression();
      Object initialValue = key.getValue();
      SPParameter keyOther = proc.getParameter(4);
      Object[] otherCols = null;
      int length = 1;
      if (keyOther != null) {
        otherCols = ((ArrayImpl) ((Constant) keyOther.getExpression()).getValue()).getValues();
        if (otherCols != null) {
          length += otherCols.length;
        }
      }
      if (ids.size() != length) {
        throw new QueryProcessingException(
            QueryPlugin.Event.TEIID30231,
            QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30231, matViewName, ids.size(), length));
      }
      final String matTableName = RelationalPlanner.MAT_PREFIX + matViewName.toUpperCase();
      MatTableInfo info = globalStore.getMatTableInfo(matTableName);
      if (!info.isValid()) {
        return CollectionTupleSource.createUpdateCountTupleSource(-1);
      }
      TempTable tempTable = globalStore.getTempTable(matTableName);
      if (!tempTable.isUpdatable()) {
        throw new QueryProcessingException(
            QueryPlugin.Event.TEIID30232,
            QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30232, matViewName));
      }
      Iterator<?> iter = ids.iterator();
      final Object[] params = new Object[length];
      StringBuilder criteria = new StringBuilder();
      for (int i = 0; i < length; i++) {
        Object id = iter.next();
        String targetTypeName = metadata.getElementType(id);
        Object value = i == 0 ? initialValue : otherCols[i - 1];
        value =
            DataTypeManager.transformValue(value, DataTypeManager.getDataTypeClass(targetTypeName));
        params[i] = value;
        if (i != 0) {
          criteria.append(" AND "); // $NON-NLS-1$
        }
        criteria.append(metadata.getFullName(id)).append(" = ?"); // $NON-NLS-1$
      }
      LogManager.logInfo(
          LogConstants.CTX_MATVIEWS,
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30012, matViewName, Arrays.toString(params)));

      String queryString =
          Reserved.SELECT
              + " * "
              + Reserved.FROM
              + ' '
              + matViewName
              + ' '
              + Reserved.WHERE
              + ' '
              + //$NON-NLS-1$
              criteria.toString()
              + ' '
              + Reserved.OPTION
              + ' '
              + Reserved.NOCACHE;
      final QueryProcessor qp =
          context
              .getQueryProcessorFactory()
              .createQueryProcessor(queryString, matViewName.toUpperCase(), context, params);
      final TupleSource ts = new BatchCollector.BatchProducerTupleSource(qp);
      return new ProxyTupleSource() {

        @Override
        protected TupleSource createTupleSource()
            throws TeiidComponentException, TeiidProcessingException {
          List<?> tuple = ts.nextTuple();
          boolean delete = false;
          if (tuple == null) {
            delete = true;
            tuple = Arrays.asList(params);
          } else {
            tuple = new ArrayList<Object>(tuple); // ensure the list is serializable
          }
          List<?> result = globalStore.updateMatViewRow(matTableName, tuple, delete);
          if (eventDistributor != null) {
            eventDistributor.updateMatViewRow(
                context.getVdbName(),
                context.getVdbVersion(),
                metadata.getName(metadata.getModelID(groupID)),
                metadata.getName(groupID),
                tuple,
                delete);
          }
          return CollectionTupleSource.createUpdateCountTupleSource(result != null ? 1 : 0);
        }

        @Override
        public void closeSource() {
          super.closeSource();
          qp.closeProcessing();
        }
      };
    }
    return null;
  }
예제 #17
0
 public boolean isTempGroupInsert() {
   return intoGroup.isTempGroupSymbol();
 }
예제 #18
0
  private TupleSource registerQuery(
      final CommandContext context, final TempTableStore contextStore, final Query query) {
    final GroupSymbol group = query.getFrom().getGroups().get(0);
    if (!group.isTempGroupSymbol()) {
      return null;
    }
    final String tableName = group.getNonCorrelationName();
    if (group.isGlobalTable()) {
      TempMetadataID matTableId = (TempMetadataID) group.getMetadataID();
      final GlobalTableStore globalStore = getGlobalStore(context, matTableId);
      final MatTableInfo info = globalStore.getMatTableInfo(tableName);
      return new ProxyTupleSource() {
        Future<Void> moreWork = null;
        TupleSource loadingTupleSource;
        DQPWorkContext newWorkContext;

        @Override
        protected TupleSource createTupleSource()
            throws TeiidComponentException, TeiidProcessingException {
          if (loadingTupleSource != null) {
            load();
          } else {
            boolean load = false;
            if (!info.isUpToDate()) {
              boolean invalidate = true;
              VDBMetaData vdb = context.getVdb();
              if (vdb != null) {
                String val = vdb.getPropertyValue("lazy-invalidate"); // $NON-NLS-1$
                if (val != null) {
                  invalidate = !Boolean.valueOf(val);
                }
              }
              load =
                  globalStore.needsLoading(
                      tableName, globalStore.getAddress(), true, false, invalidate);
              if (load) {
                load =
                    globalStore.needsLoading(
                        tableName, globalStore.getAddress(), false, false, invalidate);
              }
              if (!load) {
                synchronized (info) {
                  if (!info.isUpToDate()) {
                    RequestWorkItem workItem = context.getWorkItem();
                    info.addWaiter(workItem);
                    if (moreWork != null) {
                      moreWork.cancel(false);
                    }
                    moreWork =
                        workItem.scheduleWork(10000); // fail-safe - attempt again in 10 seconds
                    throw BlockedException.block(
                        "Blocking on mat view load", tableName); // $NON-NLS-1$
                  }
                }
              } else {
                if (!info.isValid() || executor == null) {
                  // blocking load
                  // TODO: we should probably do all loads using a temp session
                  if (info.getVdbMetaData() != null
                      && context.getDQPWorkContext() != null
                      && !info.getVdbMetaData()
                          .getFullName()
                          .equals(context.getDQPWorkContext().getVDB().getFullName())) {
                    assert executor != null;
                    // load with by pretending we're in the imported vdb
                    newWorkContext = createWorkContext(context, info.getVdbMetaData());
                    CommandContext newContext = context.clone();
                    newContext.setNewVDBState(newWorkContext);
                    loadingTupleSource =
                        loadGlobalTable(
                            newContext, group, tableName, newContext.getGlobalTableStore());
                  } else {
                    loadingTupleSource = loadGlobalTable(context, group, tableName, globalStore);
                  }
                  load();
                } else {
                  loadViaRefresh(context, tableName, context.getDQPWorkContext().getVDB(), info);
                }
              }
            }
          }
          TempTable table = globalStore.getTempTable(tableName);
          context.accessedDataObject(group.getMetadataID());
          TupleSource result =
              table.createTupleSource(
                  query.getProjectedSymbols(), query.getCriteria(), query.getOrderBy());
          cancelMoreWork();
          return result;
        }

        private void load() throws TeiidComponentException, TeiidProcessingException {
          if (newWorkContext != null) {
            try {
              newWorkContext.runInContext(
                  new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                      loadingTupleSource.nextTuple();
                      return null;
                    }
                  });
            } catch (Throwable e) {
              rethrow(e);
            }
          } else {
            loadingTupleSource.nextTuple();
          }
        }

        private void cancelMoreWork() {
          if (moreWork != null) {
            moreWork.cancel(false);
            moreWork = null;
          }
        }

        @Override
        public void closeSource() {
          if (loadingTupleSource != null) {
            loadingTupleSource.closeSource();
          }
          super.closeSource();
          cancelMoreWork();
        }
      };
    }
    // it's not expected for a blocked exception to bubble up from here, so return a tuplesource to
    // perform getOrCreateTempTable
    return new ProxyTupleSource() {
      @Override
      protected TupleSource createTupleSource()
          throws TeiidComponentException, TeiidProcessingException {
        TempTableStore tts = contextStore;

        TempTable tt =
            tts.getOrCreateTempTable(tableName, query, bufferManager, true, false, context, group);
        if (context.getDataObjects() != null) {
          Object id = RelationalPlanner.getTrackableGroup(group, context.getMetadata());
          if (id != null) {
            context.accessedDataObject(id);
          }
        }
        return tt.createTupleSource(
            query.getProjectedSymbols(), query.getCriteria(), query.getOrderBy());
      }
    };
  }
예제 #19
0
  /**
   * Get batch from child node Walk through each row of child batch Bind values to insertCommand
   * Execute insertCommand Update insertCount When no more data is available, output batch with
   * single row containing insertCount
   */
  public TupleBatch nextBatchDirect()
      throws BlockedException, TeiidComponentException, TeiidProcessingException {

    while (phase == REQUEST_CREATION) {

      checkExitConditions();

      /* If we don't have a batch to work, get the next
       */
      if (currentBatch == null) {
        if (sourceDone) {
          phase = RESPONSE_PROCESSING;
          break;
        }
        currentBatch = getChildren()[0].nextBatch(); // can throw BlockedException
        sourceDone = currentBatch.getTerminationFlag();
        this.batchRow = currentBatch.getBeginRow();

        // normally we would want to skip a 0 sized batch, but it typically represents the terminal
        // batch
        // and for implicit temp tables we need to issue an empty insert
        if (currentBatch.getRowCount() == 0
            && (!currentBatch.getTerminationFlag() || mode != Mode.ITERATOR)) {
          currentBatch = null;
          continue;
        }
      }

      int batchSize = currentBatch.getRowCount();
      int requests = 1;
      switch (mode) {
        case ITERATOR:
          if (buffer == null) {
            buffer =
                getBufferManager()
                    .createTupleBuffer(intoElements, getConnectionID(), TupleSourceType.PROCESSOR);
          }
          buffer.addTupleBatch(currentBatch, true);
          if (currentBatch.getTerminationFlag()
              && (buffer.getRowCount() != 0 || intoGroup.isImplicitTempGroupSymbol())) {
            Insert insert = new Insert(intoGroup, intoElements, null);
            buffer.close();
            insert.setTupleSource(buffer.createIndexedTupleSource(true));
            // Register insert command against source
            registerRequest(insert);
          } else {
            requests = 0;
          }
          break;
        case BATCH:
          // Register batched update command against source
          int endRow = currentBatch.getEndRow();
          List<Command> rows = new ArrayList<Command>(endRow - batchRow);
          for (int rowNum = batchRow; rowNum <= endRow; rowNum++) {

            Insert insert =
                new Insert(
                    intoGroup,
                    intoElements,
                    convertValuesToConstants(currentBatch.getTuple(rowNum), intoElements));
            rows.add(insert);
          }
          registerRequest(new BatchedUpdateCommand(rows));
          break;
        case SINGLE:
          batchSize = 1;
          // Register insert command against source
          // Defect 16036 - submit a new INSERT command to the DataManager.
          registerRequest(
              new Insert(
                  intoGroup,
                  intoElements,
                  convertValuesToConstants(currentBatch.getTuple(batchRow), intoElements)));
      }

      this.batchRow += batchSize;
      if (batchRow > currentBatch.getEndRow()) {
        currentBatch = null;
      }
      this.requestsRegistered += requests;
    }

    checkExitConditions();

    // End this node's work
    addBatchRow(Arrays.asList(insertCount));
    terminateBatches();
    return pullBatch();
  }
예제 #20
0
  /**
   * Mark the specified access node to be made dependent
   *
   * @param sourceNode Node to make dependent
   * @param dca
   * @throws TeiidComponentException
   * @throws QueryMetadataException
   */
  boolean markDependent(
      PlanNode sourceNode,
      PlanNode joinNode,
      QueryMetadataInterface metadata,
      DependentCostAnalysis dca,
      Boolean bound)
      throws QueryMetadataException, TeiidComponentException {

    boolean isLeft = joinNode.getFirstChild() == sourceNode;

    // Get new access join node properties based on join criteria
    List independentExpressions =
        (List)
            (isLeft
                ? joinNode.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS)
                : joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS));
    List dependentExpressions =
        (List)
            (isLeft
                ? joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS)
                : joinNode.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS));

    if (independentExpressions == null || independentExpressions.isEmpty()) {
      return false;
    }

    String id = "$dsc/id" + ID.getAndIncrement(); // $NON-NLS-1$
    // Create DependentValueSource and set on the independent side as this will feed the values
    joinNode.setProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE, id);

    PlanNode indNode = isLeft ? joinNode.getLastChild() : joinNode.getFirstChild();

    if (bound == null) {
      List<PlanNode> sources = NodeEditor.findAllNodes(indNode, NodeConstants.Types.SOURCE);
      for (PlanNode planNode : sources) {
        for (GroupSymbol gs : planNode.getGroups()) {
          if (gs.isTempTable()
              && metadata.getCardinality(gs.getMetadataID())
                  == QueryMetadataInterface.UNKNOWN_CARDINALITY) {
            bound = true;
            break;
          }
        }
      }
      if (bound == null) {
        bound = false;
      }
    }

    PlanNode crit =
        getDependentCriteriaNode(
            id,
            independentExpressions,
            dependentExpressions,
            indNode,
            metadata,
            dca,
            bound,
            (MakeDep) sourceNode.getProperty(Info.MAKE_DEP));

    sourceNode.addAsParent(crit);

    if (isLeft) {
      JoinUtil.swapJoinChildren(joinNode);
    }
    return true;
  }
예제 #21
0
 /**
  * @param metadata
  * @param group
  * @return
  * @throws TeiidComponentException
  * @throws QueryMetadataException
  */
 protected String getPlan(QueryMetadataInterface metadata, GroupSymbol group)
     throws TeiidComponentException, QueryMetadataException {
   return metadata.getUpdatePlan(group.getMetadataID());
 }