/** * 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.pg; import com.foundationdb.sql.server.ServerCallExplainer; import com.foundationdb.sql.server.ServerCallInvocation; import com.foundationdb.ais.model.Column; import com.foundationdb.qp.operator.QueryBindings; import com.foundationdb.qp.operator.SparseArrayQueryBindings; import com.foundationdb.qp.loadableplan.LoadableDirectObjectPlan; import com.foundationdb.qp.loadableplan.LoadableOperator; import com.foundationdb.qp.loadableplan.LoadablePlan; import com.foundationdb.server.explain.Attributes; import com.foundationdb.server.explain.CompoundExplainer; import com.foundationdb.server.explain.ExplainContext; import com.foundationdb.server.explain.Explainable; import com.foundationdb.server.explain.Label; import com.foundationdb.server.explain.PrimitiveExplainer; import com.foundationdb.server.types.TInstance; import com.foundationdb.server.types.common.types.TypesTranslator; import com.foundationdb.sql.types.DataTypeDescriptor; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class PostgresLoadablePlan { public static PostgresStatement statement(PostgresServerSession server, ServerCallInvocation invocation) { LoadablePlan<?> loadablePlan = server.getRoutineLoader().loadLoadablePlan(server.getSession(), invocation.getRoutineName()); List<String> columnNames = loadablePlan.columnNames(); List<PostgresType> columnTypes = columnTypes(loadablePlan, server.typesTranslator()); List<Column> aisColumns = Collections.nCopies(columnNames.size(), null); if (loadablePlan instanceof LoadableOperator) return new PostgresLoadableOperator((LoadableOperator)loadablePlan, invocation, columnNames, columnTypes, aisColumns, null); if (loadablePlan instanceof LoadableDirectObjectPlan) return new PostgresLoadableDirectObjectPlan((LoadableDirectObjectPlan)loadablePlan, invocation, columnNames, columnTypes, aisColumns, null); return null; } public 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; } public static List<PostgresType> columnTypes(LoadablePlan<?> plan, TypesTranslator typesTranslator) { List<PostgresType> columnTypes = new ArrayList<>(); for (int jdbcType : plan.jdbcTypes()) { DataTypeDescriptor sqlType = DataTypeDescriptor.getBuiltInDataTypeDescriptor(jdbcType); TInstance type = typesTranslator.typeForSQLType(sqlType); columnTypes.add(PostgresType.fromDerby(sqlType, type)); } return columnTypes; } public static Explainable explainable(PostgresServerSession server, final ServerCallInvocation invocation) { final LoadablePlan<?> loadablePlan = server.getRoutineLoader().loadLoadablePlan(server.getSession(), invocation.getRoutineName()); return new Explainable() { @Override public CompoundExplainer getExplainer(ExplainContext context) { Attributes atts = new Attributes(); atts.put(Label.PROCEDURE_IMPLEMENTATION, PrimitiveExplainer.getInstance(loadablePlan.getClass().getName())); return new ServerCallExplainer(invocation, atts, context); } }; } // All static methods. private PostgresLoadablePlan() { } }