/*
* 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.translator.jdbc;
import java.util.List;
import org.teiid.language.BatchedCommand;
import org.teiid.language.Command;
import org.teiid.language.Literal;
import org.teiid.language.Parameter;
import org.teiid.language.visitor.CollectorVisitor;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.TypeFacility;
/**
* This is a utility class used to translate an ICommand using a SQLConversionVisitor.
* The SQLConversionVisitor should not be invoked directly; this object will use it to
* translate the ICommand.
*/
public class TranslatedCommand {
private String sql;
private boolean prepared;
private List preparedValues;
private JDBCExecutionFactory executionFactory;
private ExecutionContext context;
/**
* Constructor, takes a SQLConversionVisitor subclass
* @param visitor a SQLConversionVisitor subclass
*/
public TranslatedCommand(ExecutionContext context, JDBCExecutionFactory executionFactory){
this.executionFactory = executionFactory;
this.context = context;
}
/**
* The method to cause this object to do it's thing. This method should
* be called right after the constructor; afterward, all of the getter methods
* can be called to retrieve results.
* @param command ICommand to be translated
* @throws TranslatorException
*/
public void translateCommand(Command command) throws TranslatorException {
SQLConversionVisitor sqlConversionVisitor = executionFactory.getSQLConversionVisitor();
sqlConversionVisitor.setExecutionContext(context);
if (executionFactory.usePreparedStatements() || hasBindValue(command)) {
sqlConversionVisitor.setPrepared(true);
}
sqlConversionVisitor.append(command);
this.sql = sqlConversionVisitor.toString();
this.preparedValues = sqlConversionVisitor.getPreparedValues();
this.prepared = command instanceof BatchedCommand?sqlConversionVisitor.isUsingBinding():sqlConversionVisitor.isPrepared();
}
/**
* Simple check to see if any values in the command should be replaced with bind values
*
* @param command
* @return
*/
private boolean hasBindValue(Command command) {
if (!CollectorVisitor.collectObjects(Parameter.class, command).isEmpty()) {
return true;
}
for (Literal l : CollectorVisitor.collectObjects(Literal.class, command)) {
if (isBindEligible(l)) {
return true;
}
}
return false;
}
/**
* @param l
* @return
*/
static boolean isBindEligible(Literal l) {
return TypeFacility.RUNTIME_TYPES.XML.equals(l.getType())
|| TypeFacility.RUNTIME_TYPES.CLOB.equals(l.getType())
|| TypeFacility.RUNTIME_TYPES.BLOB.equals(l.getType())
|| TypeFacility.RUNTIME_TYPES.GEOMETRY.equals(l.getType())
|| TypeFacility.RUNTIME_TYPES.OBJECT.equals(l.getType());
}
/**
* Return List of values to set on a prepared statement, if
* necessary.
* @return List of values to be set on a prepared statement
*/
public List getPreparedValues() {
return preparedValues;
}
/**
* Get String SQL of translated command.
* @return SQL of translated command
*/
public String getSql() {
return sql;
}
/**
* Returns whether the statement is prepared.
* @return true if the statement is prepared
*/
public boolean isPrepared() {
return prepared;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
if (prepared) {
sb.append("Prepared Values: ").append(preparedValues).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
}
sb.append("SQL: ").append(sql); //$NON-NLS-1$
return sb.toString();
}
}