/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform 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 3 of the License, or * (at your option) any later version. * * The Whole Platform 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 the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.sql.visitors; import static org.whole.lang.operations.PrettyPrinterOperation.toPrettyPrintString; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Statement; import org.whole.lang.bindings.IBindingManager; import org.whole.lang.iterators.IEntityIterator; import org.whole.lang.matchers.Matcher; import org.whole.lang.model.IEntity; import org.whole.lang.operations.InterpreterOperation; import org.whole.lang.sql.iterators.ResultSetIterator; import org.whole.lang.sql.model.ISQLEntity; import org.whole.lang.sql.model.SQLStatement; import org.whole.lang.sql.model.SQLStatements; import org.whole.lang.sql.reflect.SQLEntityDescriptorEnum; import org.whole.lang.sql.reflect.SQLFeatureDescriptorEnum; import org.whole.lang.util.DataTypeUtils; import org.whole.lang.visitors.IVisitor; import org.whole.lang.visitors.VisitException; /** * @author Riccardo Solmi, Enrico Persiani */ public class SQLInterpreterVisitor extends SQLIdentityDefaultVisitor { private static final String SQL_INTERPRETER_ERROR_MESSAGE = "SQL interpreter failure."; protected Connection connection; protected Statement statement; protected boolean batchMode = false; @Override public InterpreterOperation getOperation() { return (InterpreterOperation) super.getOperation(); } @Override public void setResultIterator(IEntityIterator<?> iterator) { if (iterator != null) iterator.setBindings(getBindings()); super.setResultIterator(iterator); } @Override public void visit(ISQLEntity entity) { if (statement != null) return; try { if (!Matcher.isAssignableAsIsFrom(SQLEntityDescriptorEnum.SQLStatement, entity) && !Matcher.match(SQLEntityDescriptorEnum.SQLStatements, entity)) throw new IllegalArgumentException("cannot interpret."); IBindingManager env = getBindings(); if (!env.wIsSet("connection")) throw new IllegalArgumentException("database connection undefined."); connection = (Connection) env.wGetValue("connection"); statement = connection.createStatement(); } catch (Exception e) { throw new VisitException(SQL_INTERPRETER_ERROR_MESSAGE, e); } } protected PreparedStatement getPreparedStatement(String sql) { try { return connection.prepareStatement(sql); } catch (Exception e) { throw new VisitException(SQL_INTERPRETER_ERROR_MESSAGE, e); } } @Override public void visit(SQLStatement entity) { try { IVisitor ov = getOperation().setVisitor(entity, 0, getOperation().getVisitor(entity, 1)); getOperation().stagedVisit(entity); getOperation().setVisitor(entity, 0, ov); entity = (SQLStatement) getResult(); String sql = toPrettyPrintString(entity); if (batchMode) statement.addBatch(sql); else { String[] names; if (entity.wGetEntityDescriptor().equals(SQLEntityDescriptorEnum.Select)) { IEntity columnExprs = entity.wGet(SQLFeatureDescriptorEnum.columnExprs); int size = columnExprs.wSize(); names = new String[size]; for (int i=0; i<size; i++) { IEntity columnExpr = columnExprs.wGet(i); if (Matcher.matchImpl(SQLEntityDescriptorEnum.ColumnExpression, columnExpr)) { IEntity alias = columnExpr.wGet(SQLFeatureDescriptorEnum.alias); if (DataTypeUtils.getDataKind(alias).isString()) names[i] = alias.wStringValue(); else { IEntity expr = columnExpr.wGet(SQLFeatureDescriptorEnum.expression); if (Matcher.matchImpl(SQLEntityDescriptorEnum.ColumnName, expr)) names[i] = expr.wStringValue(); } } } } else names = new String[0]; // PreparedStatement preparedStatement = null; // for (IEntity e : IteratorFactory.topDownIterator(entity)) { // if (preparedStatement == null) // preparedStatement = getPreparedStatement(sql); // // // } if (statement.execute(sql)) setResultIterator(new ResultSetIterator(statement.getResultSet(), names)); else { setResult(null); statement.close(); } } } catch (Exception e) { try { statement.close(); } catch (Exception e1) { } throw new VisitException(SQL_INTERPRETER_ERROR_MESSAGE, e); } finally { if (!batchMode) statement = null; } } @Override public void visit(SQLStatements entity) { try { batchMode = true; int size = entity.wSize(); for (int i=0; i<size; i++) ((ISQLEntity) entity.wGet(i)).accept(this); statement.executeBatch(); } catch (Exception e) { throw new VisitException(SQL_INTERPRETER_ERROR_MESSAGE, e); } finally { try { statement.close(); } catch (Exception e) { } statement = null; } } }