Package org.teiid.query.resolver.command

Source Code of org.teiid.query.resolver.command.SimpleQueryResolver$QueryResolverVisitor

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

package org.teiid.query.resolver.command;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.api.exception.query.UnresolvedSymbolDescription;
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.QueryPlugin;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.StoredProcedureInfo;
import org.teiid.query.metadata.SupportConstants;
import org.teiid.query.metadata.TempMetadataAdapter;
import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.resolver.CommandResolver;
import org.teiid.query.resolver.QueryResolver;
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.resolver.util.ResolverVisitor;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.lang.ArrayTable;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.ExistsCriteria;
import org.teiid.query.sql.lang.From;
import org.teiid.query.sql.lang.FromClause;
import org.teiid.query.sql.lang.Into;
import org.teiid.query.sql.lang.JoinPredicate;
import org.teiid.query.sql.lang.JoinType;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SPParameter;
import org.teiid.query.sql.lang.Select;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.lang.SubqueryCompareCriteria;
import org.teiid.query.sql.lang.SubqueryContainer;
import org.teiid.query.sql.lang.SubqueryFromClause;
import org.teiid.query.sql.lang.SubquerySetCriteria;
import org.teiid.query.sql.lang.TableFunctionReference;
import org.teiid.query.sql.lang.TextTable;
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.lang.WithQueryCommand;
import org.teiid.query.sql.lang.XMLTable;
import org.teiid.query.sql.navigator.PostOrderNavigator;
import org.teiid.query.sql.symbol.AliasSymbol;
import org.teiid.query.sql.symbol.AllInGroupSymbol;
import org.teiid.query.sql.symbol.AllSymbol;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.ExpressionSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.symbol.ScalarSubquery;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;

public class SimpleQueryResolver implements CommandResolver {

    private static final String ALL_IN_GROUP_SUFFIX = ".*"; //$NON-NLS-1$

    /**
     * @see org.teiid.query.resolver.CommandResolver#resolveCommand(org.teiid.query.sql.lang.Command, org.teiid.query.metadata.TempMetadataAdapter, boolean)
     */
    public void resolveCommand(Command command, TempMetadataAdapter metadata, boolean resolveNullLiterals)
        throws QueryMetadataException, QueryResolverException, TeiidComponentException {

      Query query = (Query) command;
     
      resolveWith(metadata, query);
       
        try {
            QueryResolverVisitor qrv = new QueryResolverVisitor(query, metadata);
            qrv.visit(query);
            ResolverVisitor visitor = (ResolverVisitor)qrv.getVisitor();
      visitor.throwException(true);
        } catch (TeiidRuntimeException e) {
            if (e.getChild() instanceof QueryMetadataException) {
                throw (QueryMetadataException)e.getChild();
            }
            if (e.getChild() instanceof QueryResolverException) {
                throw (QueryResolverException)e.getChild();
            }
            if (e.getChild() instanceof TeiidComponentException) {
                throw (TeiidComponentException)e.getChild();
            }
            throw e;
        }
                                      
        if (query.getLimit() != null) {
            ResolverUtil.resolveLimit(query.getLimit());
        }
       
        if (query.getOrderBy() != null) {
          ResolverUtil.resolveOrderBy(query.getOrderBy(), query, metadata);
        }
       
        List symbols = query.getSelect().getProjectedSymbols();
       
        if (query.getInto() != null) {
            GroupSymbol symbol = query.getInto().getGroup();
            ResolverUtil.resolveImplicitTempGroup(metadata, symbol, symbols);
        } else if (resolveNullLiterals) {
            ResolverUtil.resolveNullLiterals(symbols);
        }
    }

  static void resolveWith(TempMetadataAdapter metadata,
      QueryCommand query) throws QueryResolverException, TeiidComponentException {
    if (query.getWith() == null) {
      return;
    }
    LinkedHashSet<GroupSymbol> discoveredGroups = new LinkedHashSet<GroupSymbol>();
    for (WithQueryCommand obj : query.getWith()) {
            QueryCommand queryExpression = obj.getCommand();
           
            QueryResolver.setChildMetadata(queryExpression, query);
           
            QueryResolver.resolveCommand(queryExpression, metadata.getMetadata(), false);

            if (!discoveredGroups.add(obj.getGroupSymbol())) {
              throw new QueryResolverException(QueryPlugin.Util.getString("SimpleQueryResolver.duplicate_with", obj.getGroupSymbol())); //$NON-NLS-1$
            }
            List<? extends SingleElementSymbol> projectedSymbols = obj.getCommand().getProjectedSymbols();
            if (obj.getColumns() != null && !obj.getColumns().isEmpty()) {
              if (obj.getColumns().size() != projectedSymbols.size()) {
                throw new QueryResolverException(QueryPlugin.Util.getString("SimpleQueryResolver.mismatched_with_columns", obj.getGroupSymbol())); //$NON-NLS-1$
              }
              Iterator<ElementSymbol> iter = obj.getColumns().iterator();
              for (SingleElementSymbol singleElementSymbol : projectedSymbols) {
                ElementSymbol es = iter.next();
                es.setType(singleElementSymbol.getType());
        }
              projectedSymbols = obj.getColumns();
            }
            TempMetadataID id = ResolverUtil.addTempGroup(metadata, obj.getGroupSymbol(), projectedSymbols, true);
            obj.getGroupSymbol().setMetadataID(metadata.getMetadataStore().getTempGroupID(obj.getGroupSymbol().getName()));
            obj.getGroupSymbol().setIsTempTable(true);
            List<GroupSymbol> groups = Collections.singletonList(obj.getGroupSymbol());
            if (obj.getColumns() != null && !obj.getColumns().isEmpty()) {
              for (SingleElementSymbol singleElementSymbol : projectedSymbols) {
                  ResolverVisitor.resolveLanguageObject(singleElementSymbol, groups, metadata);
        }
            }
            if (obj.getColumns() != null && !obj.getColumns().isEmpty()) {
              Iterator<ElementSymbol> iter = obj.getColumns().iterator();
                for (TempMetadataID colid : id.getElements()) {
                ElementSymbol es = iter.next();
                es.setMetadataID(colid);
                es.setGroupSymbol(obj.getGroupSymbol());
        }
            }
        }
  }

    private static GroupSymbol resolveAllInGroup(AllInGroupSymbol allInGroupSymbol, Set<GroupSymbol> groups, QueryMetadataInterface metadata) throws QueryResolverException, QueryMetadataException, TeiidComponentException {      
        String name = allInGroupSymbol.getName();
        int index = name.lastIndexOf(ALL_IN_GROUP_SUFFIX);
        String groupAlias = name.substring(0, index);
        List<GroupSymbol> groupSymbols = ResolverUtil.findMatchingGroups(groupAlias.toUpperCase(), groups, metadata);
        if(groupSymbols.isEmpty() || groupSymbols.size() > 1) {
            String msg = QueryPlugin.Util.getString(groupSymbols.isEmpty()?"ERR.015.008.0047":"SimpleQueryResolver.ambiguous_all_in_group", allInGroupSymbol)//$NON-NLS-1$ //$NON-NLS-2$
            QueryResolverException qre = new QueryResolverException(msg);
            qre.addUnresolvedSymbol(new UnresolvedSymbolDescription(allInGroupSymbol.toString(), msg));
            throw qre;
        }

        return groupSymbols.get(0);
    }
   
    public static class QueryResolverVisitor extends PostOrderNavigator {

        private LinkedHashSet<GroupSymbol> currentGroups = new LinkedHashSet<GroupSymbol>();
        private LinkedList<GroupSymbol> discoveredGroups = new LinkedList<GroupSymbol>();
        private List<GroupSymbol> implicitGroups = new LinkedList<GroupSymbol>();
        private TempMetadataAdapter metadata;
        private Query query;
        private boolean allowImplicit = true;
       
        public QueryResolverVisitor(Query query, TempMetadataAdapter metadata) {
            super(new ResolverVisitor(metadata, null, query.getExternalGroupContexts()));
            ResolverVisitor visitor = (ResolverVisitor)getVisitor();
            visitor.setGroups(currentGroups);
            this.query = query;
            this.metadata = metadata;
        }
       
        protected void postVisitVisitor(LanguageObject obj) {
            super.postVisitVisitor(obj);
            ResolverVisitor visitor = (ResolverVisitor)getVisitor();
            try {
        visitor.throwException(false);
      } catch (TeiidException e) {
        throw new TeiidRuntimeException(e);
      }
        }
               
        /**
         * Resolving a Query requires a special ordering
         */
        public void visit(Query obj) {
            visitNode(obj.getInto());
            visitNode(obj.getFrom());
            visitNode(obj.getCriteria());
            visitNode(obj.getGroupBy());
            visitNode(obj.getHaving());
            visitNode(obj.getSelect());       
        }
       
        public void visit(GroupSymbol obj) {
            try {
                ResolverUtil.resolveGroup(obj, metadata);
            } catch (TeiidException err) {
                throw new TeiidRuntimeException(err);
            }
        }
                       
        private void resolveSubQuery(SubqueryContainer<?> obj, Collection<GroupSymbol> externalGroups) {
            Command command = obj.getCommand();
           
            QueryResolver.setChildMetadata(command, query);
            command.pushNewResolvingContext(externalGroups);
           
            try {
                QueryResolver.resolveCommand(command, metadata.getMetadata(), false);
            } catch (TeiidException err) {
                throw new TeiidRuntimeException(err);
            }
        }
       
        public void visit(AllSymbol obj) {
            try {
                List<ElementSymbol> elementSymbols = new ArrayList<ElementSymbol>();
                for (GroupSymbol group : currentGroups) {
                    elementSymbols.addAll(resolveSelectableElements(group));
                }
                obj.setElementSymbols(elementSymbols);
            } catch (TeiidComponentException err) {
                throw new TeiidRuntimeException(err);
            }
        }

        private List<ElementSymbol> resolveSelectableElements(GroupSymbol group) throws QueryMetadataException,
                                                                 TeiidComponentException {
            List<ElementSymbol> elements = ResolverUtil.resolveElementsInGroup(group, metadata);
           
            List<ElementSymbol> result = new ArrayList<ElementSymbol>(elements.size());
  
            // Look for elements that are not selectable and remove them
            for (ElementSymbol element : elements) {
                if(metadata.elementSupports(element.getMetadataID(), SupportConstants.Element.SELECT)) {
                    element = (ElementSymbol)element.clone();
                    element.setGroupSymbol(group);
                  result.add(element);
                }
            }
            return result;
        }
       
        public void visit(AllInGroupSymbol obj) {
            // Determine group that this symbol is for
            try {
                GroupSymbol group = resolveAllInGroup(obj, currentGroups, metadata);
               
                List<ElementSymbol> elements = resolveSelectableElements(group);
               
                obj.setElementSymbols(elements);
            } catch (TeiidException err) {
                throw new TeiidRuntimeException(err);
            }
        }
       
        public void visit(ScalarSubquery obj) {
            resolveSubQuery(obj, this.currentGroups);
        }
       
        public void visit(ExistsCriteria obj) {
            resolveSubQuery(obj, this.currentGroups);
        }
       
        public void visit(SubqueryCompareCriteria obj) {
            visitNode(obj.getLeftExpression());
            resolveSubQuery(obj, this.currentGroups);
            postVisitVisitor(obj);
        }
       
        public void visit(SubquerySetCriteria obj) {
            visitNode(obj.getExpression());
            resolveSubQuery(obj, this.currentGroups);
            postVisitVisitor(obj);
        }
       
        @Override
        public void visit(TextTable obj) {
          LinkedHashSet<GroupSymbol> saved = preTableFunctionReference(obj);
          this.visitNode(obj.getFile());
          try {
        obj.setFile(ResolverUtil.convertExpression(obj.getFile(), DataTypeManager.DefaultDataTypes.CLOB, metadata));
      } catch (QueryResolverException e) {
        throw new TeiidRuntimeException(e);
      }
      postTableFunctionReference(obj, saved);
            //set to fixed width if any column has width specified
            for (TextTable.TextColumn col : obj.getColumns()) {
        if (col.getWidth() != null) {
          obj.setFixedWidth(true);
          break;
        }
      }
        }
       
        @Override
        public void visit(ArrayTable obj) {
          LinkedHashSet<GroupSymbol> saved = preTableFunctionReference(obj);
          visitNode(obj.getArrayValue());
      postTableFunctionReference(obj, saved);
        }
       
        @Override
        public void visit(XMLTable obj) {
          LinkedHashSet<GroupSymbol> saved = preTableFunctionReference(obj);
          visitNodes(obj.getPassing());
      postTableFunctionReference(obj, saved);
      try {
        obj.compileXqueryExpression();
        for (XMLTable.XMLColumn column : obj.getColumns()) {
          if (column.getDefaultExpression() == null) {
            continue;
          }
          ResolverVisitor.resolveLanguageObject(column.getDefaultExpression(), metadata);
          Expression ex = ResolverUtil.convertExpression(column.getDefaultExpression(), DataTypeManager.getDataTypeName(column.getSymbol().getType()), metadata);
          column.setDefaultExpression(ex);
        }
      } catch (TeiidException e) {
        throw new TeiidRuntimeException(e);
      }
        }
       
        public LinkedHashSet<GroupSymbol> preTableFunctionReference(TableFunctionReference tfr) {
          LinkedHashSet<GroupSymbol> saved = new LinkedHashSet<GroupSymbol>(this.currentGroups);
          if (allowImplicit) {
            currentGroups.addAll(this.implicitGroups);
          }
          return saved;
        }
       
        public void postTableFunctionReference(TableFunctionReference obj, LinkedHashSet<GroupSymbol> saved) {
      //we didn't create a true external context, so we manually mark external
      for (ElementSymbol symbol : ElementCollectorVisitor.getElements(obj, false)) {
        if (symbol.isExternalReference()) {
          continue;
        }
        if (implicitGroups.contains(symbol.getGroupSymbol())) {
          symbol.setIsExternalReference(true);
        }
      }
      if (allowImplicit) {
            this.currentGroups.clear();
            this.currentGroups.addAll(saved);
      }
            discoveredGroup(obj.getGroupSymbol());
            try {
                ResolverUtil.addTempGroup(metadata, obj.getGroupSymbol(), obj.getProjectedSymbols(), false);
            } catch (QueryResolverException err) {
                throw new TeiidRuntimeException(err);
            }
            obj.getGroupSymbol().setMetadataID(metadata.getMetadataStore().getTempGroupID(obj.getGroupSymbol().getName()));
            //now resolve the projected symbols
            Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
            groups.add(obj.getGroupSymbol());
            for (ElementSymbol symbol : obj.getProjectedSymbols()) {
                try {
          ResolverVisitor.resolveLanguageObject(symbol, groups, null, metadata);
        } catch (TeiidException e) {
          throw new TeiidRuntimeException(e);
        }       
      }
        }
       
        public void visit(SubqueryFromClause obj) {
          Collection<GroupSymbol> externalGroups = this.currentGroups;
          if (obj.isTable() && allowImplicit) {
            externalGroups = new ArrayList<GroupSymbol>(externalGroups);
            externalGroups.addAll(this.implicitGroups);
          }
            resolveSubQuery(obj, externalGroups);
            discoveredGroup(obj.getGroupSymbol());
            try {
                ResolverUtil.addTempGroup(metadata, obj.getGroupSymbol(), obj.getCommand().getProjectedSymbols(), false);
            } catch (QueryResolverException err) {
                throw new TeiidRuntimeException(err);
            }
            obj.getGroupSymbol().setMetadataID(metadata.getMetadataStore().getTempGroupID(obj.getGroupSymbol().getName()));
        }
                       
        public void visit(UnaryFromClause obj) {
            GroupSymbol group = obj.getGroup();
            visitNode(group);
            try {
              if (!group.isProcedure() && metadata.isXMLGroup(group.getMetadataID())) {
                  throw new QueryResolverException("ERR.015.008.0003", QueryPlugin.Util.getString("ERR.015.008.0003")); //$NON-NLS-1$ //$NON-NLS-2$
              }
              discoveredGroup(group);
              if (group.isProcedure()) {
                  createProcRelational(obj);
              }
            } catch(TeiidException e) {
                throw new TeiidRuntimeException(e);                       
      }
        }
       
        private void discoveredGroup(GroupSymbol group) {
          discoveredGroups.add(group);
          if (allowImplicit) {
            implicitGroups.add(group);
          }
        }

    private void createProcRelational(UnaryFromClause obj)
        throws TeiidComponentException, QueryMetadataException,
        QueryResolverException {
      GroupSymbol group = obj.getGroup();
      String fullName = metadata.getFullName(group.getMetadataID());
      String queryName = group.getName();
     
      StoredProcedureInfo storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(fullName);

      StoredProcedure storedProcedureCommand = new StoredProcedure();
      storedProcedureCommand.setProcedureRelational(true);
      storedProcedureCommand.setProcedureName(fullName);
     
      List<SPParameter> metadataParams = storedProcedureInfo.getParameters();
     
      Query procQuery = new Query();
      From from = new From();
      from.addClause(new SubqueryFromClause("X", storedProcedureCommand)); //$NON-NLS-1$
      procQuery.setFrom(from);
      Select select = new Select();
      select.addSymbol(new AllInGroupSymbol("X.*")); //$NON-NLS-1$
      procQuery.setSelect(select);
     
      List<String> accessPatternElementNames = new LinkedList<String>();
     
      int paramIndex = 1;
     
      for (SPParameter metadataParameter : metadataParams) {
          SPParameter clonedParam = (SPParameter)metadataParameter.clone();
          if (clonedParam.getParameterType()==ParameterInfo.IN || metadataParameter.getParameterType()==ParameterInfo.INOUT) {
              ElementSymbol paramSymbol = clonedParam.getParameterSymbol();
              Reference ref = new Reference(paramSymbol);
              clonedParam.setExpression(ref);
              clonedParam.setIndex(paramIndex++);
              storedProcedureCommand.setParameter(clonedParam);
             
              String aliasName = paramSymbol.getShortName();
             
              if (metadataParameter.getParameterType()==ParameterInfo.INOUT) {
                  aliasName += "_IN"; //$NON-NLS-1$
              }
             
              SingleElementSymbol newSymbol = new AliasSymbol(aliasName, new ExpressionSymbol(paramSymbol.getShortName(), ref));
             
              select.addSymbol(newSymbol);
              accessPatternElementNames.add(queryName + ElementSymbol.SEPARATOR + aliasName);
          }
      }
     
      QueryResolver.resolveCommand(procQuery, metadata.getMetadata());
     
      List<SingleElementSymbol> projectedSymbols = procQuery.getProjectedSymbols();
     
      HashSet<String> foundNames = new HashSet<String>();
     
      for (SingleElementSymbol ses : projectedSymbols) {
          if (!foundNames.add(ses.getShortCanonicalName())) {
              throw new QueryResolverException(QueryPlugin.Util.getString("SimpleQueryResolver.Proc_Relational_Name_conflict", fullName)); //$NON-NLS-1$                           
          }
      }
     
      TempMetadataID id = metadata.getMetadataStore().getTempGroupID(queryName);

      if (id == null) {
          metadata.getMetadataStore().addTempGroup(queryName, projectedSymbols, true);
         
          id = metadata.getMetadataStore().getTempGroupID(queryName);
          id.setOriginalMetadataID(storedProcedureCommand.getProcedureID());
          if (!accessPatternElementNames.isEmpty()) {
            List<TempMetadataID> accessPatternIds = new LinkedList<TempMetadataID>();
           
            for (String name : accessPatternElementNames) {
                accessPatternIds.add(metadata.getMetadataStore().getTempElementID(name));
            }
           
            id.setAccessPatterns(Arrays.asList(new TempMetadataID("procedure access pattern", accessPatternIds))); //$NON-NLS-1$
          }
      }
     
      group.setMetadataID(id);
     
        obj.setExpandedCommand(procQuery);
    }
       
        /**
         * @see org.teiid.query.sql.navigator.PreOrPostOrderNavigator#visit(org.teiid.query.sql.lang.Into)
         */
        public void visit(Into obj) {
            if (!obj.getGroup().isImplicitTempGroupSymbol()) {
                super.visit(obj);
            }
        }

        public void visit(JoinPredicate obj) {
            assert currentGroups.isEmpty();
          List<GroupSymbol> tempImplicitGroups = new ArrayList<GroupSymbol>(discoveredGroups);
          discoveredGroups.clear();
            visitNode(obj.getLeftClause());
            List<GroupSymbol> leftGroups = new ArrayList<GroupSymbol>(discoveredGroups);
          discoveredGroups.clear();
            visitNode(obj.getRightClause());
            discoveredGroups.addAll(leftGroups);
            addDiscoveredGroups();
            visitNodes(obj.getJoinCriteria());
            discoveredGroups.addAll(currentGroups);
            currentGroups.clear();
            discoveredGroups.addAll(tempImplicitGroups);
        }

    private void addDiscoveredGroups() {
      for (GroupSymbol group : discoveredGroups) {
        if (!this.currentGroups.add(group)) {
                  String msg = QueryPlugin.Util.getString("ERR.015.008.0046", group.getName()); //$NON-NLS-1$
                  QueryResolverException qre = new QueryResolverException("ERR.015.008.0046", msg); //$NON-NLS-1$
                  qre.addUnresolvedSymbol(new UnresolvedSymbolDescription(group.toString(), msg));
                  throw new TeiidRuntimeException(qre);
              }
      }
            discoveredGroups.clear();
    }
               
        public void visit(From obj) {
            assert currentGroups.isEmpty();
            for (FromClause clause : (List<FromClause>)obj.getClauses()) {
        checkImplicit(clause);
      }
            super.visit(obj);
            addDiscoveredGroups();
        }

    private void checkImplicit(FromClause clause) {
      if (clause instanceof JoinPredicate) {
        JoinPredicate jp = (JoinPredicate)clause;
        if (jp.getJoinType() == JoinType.JOIN_FULL_OUTER || jp.getJoinType() == JoinType.JOIN_RIGHT_OUTER) {
          allowImplicit = false;
          return;
        }
        checkImplicit(jp.getLeftClause());
        if (allowImplicit) {
          checkImplicit(jp.getRightClause());
        }
      }
    }
    }
}
TOP

Related Classes of org.teiid.query.resolver.command.SimpleQueryResolver$QueryResolverVisitor

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