/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.sql.embedded; import com.foundationdb.sql.embedded.JDBCResultSetMetaData.ResultColumn; import com.foundationdb.qp.loadableplan.LoadableOperator; import com.foundationdb.qp.loadableplan.LoadablePlan; import com.foundationdb.qp.operator.QueryBindings; import com.foundationdb.qp.operator.SparseArrayQueryBindings; import com.foundationdb.server.error.UnsupportedSQLException; import com.foundationdb.server.types.TInstance; import com.foundationdb.sql.parser.CallStatementNode; import com.foundationdb.sql.server.ServerCallContextStack; import com.foundationdb.sql.server.ServerCallInvocation; import com.foundationdb.sql.types.DataTypeDescriptor; import java.util.ArrayList; import java.util.List; class ExecutableLoadableOperator extends ExecutableQueryOperatorStatement { private ServerCallInvocation invocation; public static ExecutableStatement executableStatement(ServerCallInvocation invocation, JDBCParameterMetaData parameterMetaData, CallStatementNode call, EmbeddedQueryContext context) { JDBCConnection conn = context.getServer(); LoadablePlan<?> plan = conn.getRoutineLoader().loadLoadablePlan(conn.getSession(), invocation.getRoutineName()); long aisGeneration = context.getAIS().getGeneration(); JDBCResultSetMetaData resultSetMetaData = resultSetMetaData(plan, context); if (plan instanceof LoadableOperator) return new ExecutableLoadableOperator((LoadableOperator)plan, invocation, aisGeneration, resultSetMetaData, parameterMetaData); throw new UnsupportedSQLException("Unsupported loadable plan", call); } protected ExecutableLoadableOperator(LoadableOperator loadableOperator, ServerCallInvocation invocation, long aisGeneration, JDBCResultSetMetaData resultSetMetaData, JDBCParameterMetaData parameterMetaData) { super(loadableOperator.plan(), aisGeneration, resultSetMetaData, parameterMetaData, null); this.invocation = invocation; } @Override public ExecuteResults execute(EmbeddedQueryContext context, QueryBindings bindings) { bindings = setParameters(bindings, invocation); ServerCallContextStack stack = ServerCallContextStack.get(); boolean success = false; stack.push(context, invocation); try { ExecuteResults results = super.execute(context, bindings); success = true; return results; } finally { stack.pop(context, invocation, success); } } protected static JDBCResultSetMetaData resultSetMetaData(LoadablePlan<?> plan, EmbeddedQueryContext context) { List<String> columnNames = plan.columnNames(); int[] jdbcTypes = plan.jdbcTypes(); List<ResultColumn> columns = new ArrayList<>(jdbcTypes.length); for (int i = 0; i < jdbcTypes.length; i++) { String name = columnNames.get(i); int jdbcType = jdbcTypes[i]; DataTypeDescriptor sqlType = DataTypeDescriptor.getBuiltInDataTypeDescriptor(jdbcType); TInstance type = context.getTypesTranslator().typeForSQLType(sqlType); ResultColumn column = new ResultColumn(name, jdbcType, sqlType, null, type, null); columns.add(column); } return new JDBCResultSetMetaData(context.getTypesTranslator(), columns); } protected static QueryBindings setParameters(QueryBindings bindings, ServerCallInvocation invocation) { if (!invocation.parametersInOrder()) { if (invocation.hasParameters()) { QueryBindings calleeBindings = new SparseArrayQueryBindings(); invocation.copyParameters(bindings, calleeBindings); bindings = calleeBindings; } else { invocation.copyParameters(null, bindings); } } return bindings; } }