Пример #1
0
  private void checkForSharedSourceCommand(AccessNode aNode) {
    // create a top level key to avoid the full command toString
    String modelName = aNode.getModelName();
    Command cmd = aNode.getCommand();

    // don't share full scans against internal sources, it's a waste of buffering
    if (CoreConstants.SYSTEM_MODEL.equals(modelName)
        || CoreConstants.SYSTEM_ADMIN_MODEL.equals(modelName)
        || TempMetadataAdapter.TEMP_MODEL.getName().equals(modelName)) {
      if (!(cmd instanceof Query)) {
        return;
      }
      Query query = (Query) cmd;
      if (query.getOrderBy() == null && query.getCriteria() == null) {
        return;
      }
    }

    AccessNode other = sharedCommands.get(cmd);
    if (other == null) {
      sharedCommands.put(cmd, aNode);
    } else {
      if (other.info == null) {
        other.info = new RegisterRequestParameter.SharedAccessInfo();
        other.info.id = sharedId.getAndIncrement();
      }
      other.info.sharingCount++;
      aNode.info = other.info;
    }
  }
Пример #2
0
 @Test
 public void testOrderBySymbolName() throws Exception {
   String sql = "select e1 from pm1.g1 order by e1"; // $NON-NLS-1$
   String expected = "SELECT g_0.e1 AS c_0 FROM pm1.g1 AS g_0 ORDER BY c_0"; // $NON-NLS-1$
   Query command =
       (Query) helpTest(sql, expected, true, false, RealMetadataFactory.example1Cached());
   assertEquals(
       ((Symbol) command.getOrderBy().getSortKeys().get(0)).getName(), "c_0"); // $NON-NLS-1$
   assertEquals(
       ((Symbol) command.getProjectedSymbols().get(0)).getShortName(), "c_0"); // $NON-NLS-1$
 }
Пример #3
0
 /** Ensures that views are named with v_ even without metadata */
 @Test
 public void testViewAliasing() throws Exception {
   String sql = "select y.e1 from (select pm1.g1.e1 from pm1.g1) y"; // $NON-NLS-1$
   Query command = (Query) QueryParser.getQueryParser().parseCommand(sql);
   ((ElementSymbol) command.getSelect().getSymbol(0))
       .setGroupSymbol(new GroupSymbol("y")); // $NON-NLS-1$
   command.acceptVisitor(new AliasGenerator(true));
   assertEquals(
       "SELECT v_0.c_0 FROM (SELECT g_0.e1 AS c_0 FROM pm1.g1 AS g_0) AS v_0",
       command.toString()); // $NON-NLS-1$
 }
 @Override
 public void visit(Query obj) {
   preVisitVisitor(obj);
   visitNodes(obj.getWith());
   visitNode(obj.getSelect());
   visitNode(obj.getInto());
   visitNode(obj.getFrom());
   visitNode(obj.getCriteria());
   visitNode(obj.getGroupBy());
   visitNode(obj.getHaving());
   visitNode(obj.getOrderBy());
   visitNode(obj.getLimit());
   visitNode(obj.getOption());
   postVisitVisitor(obj);
 }
Пример #5
0
 @Override
 public CountResponse executeCount(Query query, List<SQLParam> parameters) {
   ConnectionImpl connection = null;
   try {
     String sql = query.toString();
     LogManager.logDetail(LogConstants.CTX_ODATA, "Teiid-Query:", sql); // $NON-NLS-1$
     connection = getConnection();
     final PreparedStatementImpl stmt = connection.prepareStatement(sql);
     if (!parameters.isEmpty()) {
       for (int i = 0; i < parameters.size(); i++) {
         stmt.setObject(i + 1, parameters.get(i).value, parameters.get(i).sqlType);
       }
     }
     ResultSet rs = stmt.executeQuery();
     rs.next();
     int count = rs.getInt(1);
     rs.close();
     stmt.close();
     return Responses.count(count);
   } catch (Exception e) {
     throw new ServerErrorException(e.getMessage(), e);
   } finally {
     try {
       if (connection != null) {
         connection.close();
       }
     } catch (SQLException e) {
     }
   }
 }
  private QueryCommand buildSubquery(Expression projected) {
    Criteria criteria = null;
    for (ForeignKey fk : this.childTable.getForeignKeys()) {
      if (fk.getPrimaryKey().getParent().equals(this.parent)) {
        List<String> refColumns = fk.getReferenceColumns();
        if (refColumns == null) {
          refColumns = ODataSQLBuilder.getColumnNames(childTable.getPrimaryKey().getColumns());
        }

        List<String> pkColumns =
            ODataSQLBuilder.getColumnNames(parent.getPrimaryKey().getColumns());
        List<Criteria> critList = new ArrayList<Criteria>();

        for (int i = 0; i < refColumns.size(); i++) {
          critList.add(
              new CompareCriteria(
                  new ElementSymbol(pkColumns.get(i), this.parentGroup),
                  CompareCriteria.EQ,
                  new ElementSymbol(refColumns.get(i), this.childGroup)));
        }

        criteria = critList.get(0);
        for (int i = 1; i < critList.size(); i++) {
          criteria = new CompoundCriteria(CompoundCriteria.AND, criteria, critList.get(i));
        }
      }
    }
    Select s1 = new Select();
    s1.addSymbol(projected);
    From f1 = new From();
    f1.addGroup(this.childGroup);
    Query q1 = new Query();
    q1.setSelect(s1);
    q1.setFrom(f1);
    q1.setCriteria(criteria);

    return q1;
  }
Пример #7
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;
  }
Пример #8
0
 /** @see org.teiid.query.sql.lang.Command#areResultsCachable() */
 public boolean areResultsCachable() {
   return Query.areColumnsCachable(getProjectedSymbols());
 }
Пример #9
0
  public Object lookupCodeValue(
      CommandContext context,
      String codeTableName,
      String returnElementName,
      String keyElementName,
      Object keyValue)
      throws BlockedException, TeiidComponentException, TeiidProcessingException {
    // we are not using a resolved form of a lookup, so we canonicallize with upper case
    codeTableName = codeTableName.toUpperCase();
    keyElementName = keyElementName.toUpperCase();
    returnElementName = returnElementName.toUpperCase();
    String matTableName =
        CODE_PREFIX
            + codeTableName
            + ElementSymbol.SEPARATOR
            + keyElementName
            + ElementSymbol.SEPARATOR
            + returnElementName;

    TupleSource ts = context.getCodeLookup(matTableName, keyValue);
    if (ts == null) {
      QueryMetadataInterface metadata = context.getMetadata();

      TempMetadataID id =
          context
              .getGlobalTableStore()
              .getCodeTableMetadataId(
                  codeTableName, returnElementName, keyElementName, matTableName);

      ElementSymbol keyElement = new ElementSymbol(keyElementName, new GroupSymbol(matTableName));
      ElementSymbol returnElement =
          new ElementSymbol(returnElementName, new GroupSymbol(matTableName));
      keyElement.setType(
          DataTypeManager.getDataTypeClass(
              metadata.getElementType(
                  metadata.getElementID(
                      codeTableName + ElementSymbol.SEPARATOR + keyElementName))));
      returnElement.setType(
          DataTypeManager.getDataTypeClass(
              metadata.getElementType(
                  metadata.getElementID(
                      codeTableName + ElementSymbol.SEPARATOR + returnElementName))));

      Query query =
          RelationalPlanner.createMatViewQuery(
              id, matTableName, Arrays.asList(returnElement), true);
      query.setCriteria(
          new CompareCriteria(keyElement, CompareCriteria.EQ, new Constant(keyValue)));

      ts = registerQuery(context, context.getTempTableStore(), query);
    }
    try {
      List<?> row = ts.nextTuple();
      Object result = null;
      if (row != null) {
        result = row.get(0);
      }
      ts.closeSource();
      return result;
    } catch (BlockedException e) {
      context.putCodeLookup(matTableName, keyValue, ts);
      throw e;
    }
  }
Пример #10
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());
      }
    };
  }
Пример #11
0
  @Override
  public EntityList executeSQL(
      Query query,
      List<SQLParam> parameters,
      EdmEntitySet entitySet,
      LinkedHashMap<String, Boolean> projectedColumns,
      QueryInfo queryInfo) {
    ConnectionImpl connection = null;
    try {
      boolean cache = queryInfo != null && this.batchSize > 0;
      if (cache) {
        CacheHint hint = new CacheHint();
        hint.setTtl(this.cacheTime);
        hint.setScope(CacheDirective.Scope.USER);
        hint.setMinRows(Long.valueOf(this.batchSize));
        query.setCacheHint(hint);
      }

      boolean getCount = false;
      if (queryInfo != null) {
        getCount = queryInfo.inlineCount == InlineCount.ALLPAGES;
        if (!getCount && (queryInfo.top != null || queryInfo.skip != null)) {
          if (queryInfo.top != null && queryInfo.skip != null) {
            query.setLimit(new Limit(new Constant(queryInfo.skip), new Constant(queryInfo.top)));
          } else if (queryInfo.top != null) {
            query.setLimit(new Limit(new Constant(0), new Constant(queryInfo.top)));
          }
        }
      }

      connection = getConnection();
      String sessionId = connection.getServerConnection().getLogonResult().getSessionID();

      String skipToken = null;
      if (queryInfo != null && queryInfo.skipToken != null) {
        skipToken = queryInfo.skipToken;
        if (cache) {
          int idx = queryInfo.skipToken.indexOf(DELIMITER);
          sessionId = queryInfo.skipToken.substring(0, idx);
          skipToken = queryInfo.skipToken.substring(idx + 2);
        }
      }
      String sql = query.toString();
      if (cache) {
        sql += " /* " + sessionId + " */"; // $NON-NLS-1$ //$NON-NLS-2$
      }
      LogManager.logDetail(LogConstants.CTX_ODATA, "Teiid-Query:", sql); // $NON-NLS-1$

      final PreparedStatement stmt =
          connection.prepareStatement(
              sql,
              cache ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY,
              ResultSet.CONCUR_READ_ONLY);
      if (parameters != null && !parameters.isEmpty()) {
        for (int i = 0; i < parameters.size(); i++) {
          stmt.setObject(i + 1, parameters.get(i).value, parameters.get(i).sqlType);
        }
      }

      final ResultSet rs = stmt.executeQuery();

      if (projectedColumns == null) {
        projectedColumns = new LinkedHashMap<String, Boolean>();
        for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
          projectedColumns.put(rs.getMetaData().getColumnLabel(i + 1), Boolean.TRUE);
        }
      }

      EntityList result = new EntityList(invalidCharacterReplacement);

      HashMap<String, EdmProperty> propertyTypes = new HashMap<String, EdmProperty>();

      EdmEntityType entityType = entitySet.getType();
      Iterator<EdmProperty> propIter = entityType.getProperties().iterator();
      while (propIter.hasNext()) {
        EdmProperty prop = propIter.next();
        propertyTypes.put(prop.getName(), prop);
      }

      // skip to the initial position
      int count = 0;
      int skipSize = 0;
      // skip based upon the skip value
      if (getCount && queryInfo.skip != null) {
        skipSize = queryInfo.skip;
      }
      // skip based upon the skipToken
      if (skipToken != null) {
        skipSize += Integer.parseInt(skipToken);
      }
      if (skipSize > 0) {
        count += skip(cache, rs, skipSize);
      }

      // determine the number of records to return
      int size = batchSize;
      int top = Integer.MAX_VALUE;
      if (getCount && queryInfo.top != null) {
        top = queryInfo.top;
        size = top;
        if (batchSize > 0) {
          size = Math.min(batchSize, size);
        }
      } else if (size < 1) {
        size = Integer.MAX_VALUE;
      }

      // build the results
      for (int i = 0; i < size; i++) {
        if (!rs.next()) {
          break;
        }
        count++;
        result.addEntity(rs, propertyTypes, projectedColumns, entitySet);
      }

      // set the count
      if (getCount) {
        if (!cache) {
          while (rs.next()) {
            count++;
          }
        } else {
          rs.last();
          count = rs.getRow();
        }
      }
      result.setCount(count);

      // set the skipToken if needed
      if (cache && result.size() == this.batchSize) {
        int end = skipSize + result.size();
        if (getCount) {
          if (end < Math.min(top, count)) {
            result.setNextToken(nextToken(cache, sessionId, end));
          }
        } else if (rs.next()) {
          result.setNextToken(nextToken(cache, sessionId, end));
          // will force the entry to cache or is effectively a no-op when already cached
          rs.last();
        }
      }
      return result;
    } catch (Exception e) {
      throw new ServerErrorException(e.getMessage(), e);
    } finally {
      if (connection != null) {
        try {
          connection.close();
        } catch (SQLException e) {
        }
      }
    }
  }
Пример #12
0
  @Override
  public void createEntity(DataRequest request, Entity entity, EntityResponse response)
      throws ODataLibraryException, ODataApplicationException {

    EdmEntityType entityType = request.getEntitySet().getEntityType();

    String txn;
    try {
      txn = getClient().startTransaction();
    } catch (SQLException e) {
      throw new ODataApplicationException(
          e.getMessage(),
          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(),
          Locale.getDefault(),
          e);
    }
    boolean success = false;

    try {
      List<ExpandNode> expands = new ArrayList<TeiidServiceHandler.ExpandNode>();
      UpdateResponse updateResponse =
          performDeepInsert(
              request.getODataRequest().getRawBaseUri(),
              request.getUriInfo(),
              entityType,
              entity,
              expands);

      if (updateResponse != null && updateResponse.getUpdateCount() == 1) {
        ODataSQLBuilder visitor =
            new ODataSQLBuilder(
                this.odata,
                getClient().getMetadataStore(),
                true,
                false,
                request.getODataRequest().getRawBaseUri(),
                this.serviceMetadata,
                this.nameGenerator);

        Query query =
            visitor.selectWithEntityKey(
                entityType, entity, updateResponse.getGeneratedKeys(), expands);
        LogManager.logDetail(
            LogConstants.CTX_ODATA,
            null,
            "created entity = ",
            entityType.getName(),
            " with key=",
            query.getCriteria().toString()); // $NON-NLS-1$ //$NON-NLS-2$

        EntityCollectionResponse result =
            new EntityCollectionResponse(
                request.getODataRequest().getRawBaseUri(), visitor.getContext());

        getClient().executeSQL(query, visitor.getParameters(), false, null, null, null, 1, result);

        if (!result.getEntities().isEmpty()) {
          entity = result.getEntities().get(0);
          String location =
              EntityResponse.buildLocation(
                  request.getODataRequest().getRawBaseUri(),
                  entity,
                  request.getEntitySet().getName(),
                  entityType);
          entity.setId(new URI(location));
        }
        response.writeCreatedEntity(request.getEntitySet(), entity);
      } else {
        response.writeNotModified();
      }
      getClient().commit(txn);
      success = true;
    } catch (SQLException e) {
      throw new ODataApplicationException(
          e.getMessage(),
          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(),
          Locale.getDefault(),
          e);
    } catch (URISyntaxException e) {
      throw new ODataApplicationException(
          e.getMessage(),
          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(),
          Locale.getDefault(),
          e);
    } catch (TeiidException e) {
      throw new ODataApplicationException(
          e.getMessage(),
          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(),
          Locale.getDefault(),
          e);
    } catch (EdmPrimitiveTypeException e) {
      throw new ODataApplicationException(
          e.getMessage(),
          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(),
          Locale.getDefault(),
          e);
    } finally {
      if (!success) {
        try {
          getClient().rollback(txn);
        } catch (SQLException e1) {
          // ignore
        }
      }
    }
  }