/* * 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.cdk; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.teiid.core.TeiidException; import org.teiid.core.TeiidRuntimeException; import org.teiid.dqp.internal.datamgr.LanguageBridgeFactory; import org.teiid.language.LanguageFactory; import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.optimizer.relational.AliasGenerator; import org.teiid.query.parser.QueryParser; import org.teiid.query.resolver.QueryResolver; import org.teiid.query.rewriter.QueryRewriter; import org.teiid.query.sql.lang.Command; import org.teiid.query.sql.lang.Query; import org.teiid.query.sql.lang.Select; import org.teiid.query.sql.lang.SubqueryContainer; import org.teiid.query.sql.navigator.DeepPostOrderNavigator; import org.teiid.query.sql.navigator.PreOrderNavigator; import org.teiid.query.sql.symbol.Expression; import org.teiid.query.sql.symbol.MultipleElementSymbol; import org.teiid.query.sql.symbol.Reference; import org.teiid.query.sql.visitor.ExpressionMappingVisitor; import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor; /** * Convert a query string into a SQL language parse tree. */ public class CommandBuilder { public static LanguageFactory getLanuageFactory() { return LanguageFactory.INSTANCE; } private QueryMetadataInterface metadata; private LanguageBridgeFactory languageBridgeFactory; /** * @param metadata The metadata describing the datasource which the query is for. */ public CommandBuilder(QueryMetadataInterface metadata) { this.metadata = metadata; this.languageBridgeFactory = new LanguageBridgeFactory(metadata); } public LanguageBridgeFactory getLanguageBridgeFactory() { return languageBridgeFactory; } public org.teiid.language.Command getCommand(String queryString) { return getCommand(queryString, false, false); } public org.teiid.language.Command getCommand(String queryString, boolean generateAliases, boolean supportsGroupAlias) { Command command = null; try { command = QueryParser.getQueryParser().parseCommand(queryString); QueryResolver.resolveCommand(command, metadata); command = QueryRewriter.rewrite(command, metadata, null); expandAllSymbol(command); if (generateAliases) { command = (Command)command.clone(); command.acceptVisitor(new AliasGenerator(supportsGroupAlias)); } //the language bridge doesn't expect References ValueIteratorProviderCollectorVisitor v = new ValueIteratorProviderCollectorVisitor(); v.setCollectLateral(true); PreOrderNavigator.doVisit(command, v); for (SubqueryContainer<?> container : v.getValueIteratorProviders()) { ExpressionMappingVisitor visitor = new ExpressionMappingVisitor(null) { @Override public Expression replaceExpression(Expression element) { if (element instanceof Reference) { return ((Reference)element).getExpression(); } return element; } }; DeepPostOrderNavigator.doVisit(command, visitor); } return languageBridgeFactory.translate(command); } catch (TeiidException e) { throw new TeiidRuntimeException(e); } } /** * Convert the "*" in "select * from..." to the list of column names for the data source. */ protected void expandAllSymbol(Command command) { if (command instanceof Query) { Query query = (Query) command; Select select = query.getSelect(); List<Expression> originalSymbols = select.getSymbols(); List<Expression> expandedSymbols = new ArrayList<Expression>(); for (Iterator<Expression> i = originalSymbols.iterator(); i.hasNext(); ) { Expression next = i.next(); if (next instanceof MultipleElementSymbol) { MultipleElementSymbol allSymbol = (MultipleElementSymbol) next; expandedSymbols.addAll(allSymbol.getElementSymbols()); } else { expandedSymbols.add(next); } } select.setSymbols(expandedSymbols); } } }