io.crate.action.sql.DDLStatementDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for io.crate.action.sql.DDLStatementDispatcher.java

Source

/*
 * Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  Crate licenses
 * this file to you under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 * However, if you have executed another commercial license agreement
 * with Crate these terms will supersede the license and you may use the
 * software solely pursuant to the terms of the relevant commercial agreement.
 */

package io.crate.action.sql;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import io.crate.action.FutureActionListener;
import io.crate.analyze.*;
import io.crate.blob.v2.BlobIndicesService;
import io.crate.executor.transport.*;
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.Singleton;

import javax.annotation.Nullable;
import java.util.Locale;
import java.util.UUID;

/**
 * visitor that dispatches requests based on Analysis class to different actions.
 * <p>
 * Its methods return a future returning a Long containing the response rowCount.
 * If the future returns <code>null</code>, no row count shall be created.
 */
@Singleton
public class DDLStatementDispatcher {

    private final BlobIndicesService blobIndicesService;
    private final TransportActionProvider transportActionProvider;
    private final TableCreator tableCreator;
    private final AlterTableOperation alterTableOperation;
    private final RepositoryService repositoryService;
    private final SnapshotRestoreDDLDispatcher snapshotRestoreDDLDispatcher;

    private final InnerVisitor innerVisitor = new InnerVisitor();

    @Inject
    public DDLStatementDispatcher(BlobIndicesService blobIndicesService, TableCreator tableCreator,
            AlterTableOperation alterTableOperation, RepositoryService repositoryService,
            SnapshotRestoreDDLDispatcher snapshotRestoreDDLDispatcher,
            TransportActionProvider transportActionProvider) {
        this.blobIndicesService = blobIndicesService;
        this.tableCreator = tableCreator;
        this.alterTableOperation = alterTableOperation;
        this.transportActionProvider = transportActionProvider;
        this.repositoryService = repositoryService;
        this.snapshotRestoreDDLDispatcher = snapshotRestoreDDLDispatcher;
    }

    public ListenableFuture<Long> dispatch(AnalyzedStatement analyzedStatement, UUID jobId) {
        return innerVisitor.process(analyzedStatement, jobId);
    }

    private class InnerVisitor extends AnalyzedStatementVisitor<UUID, ListenableFuture<Long>> {

        @Override
        protected ListenableFuture<Long> visitAnalyzedStatement(AnalyzedStatement analyzedStatement, UUID jobId) {
            throw new UnsupportedOperationException(
                    String.format(Locale.ENGLISH, "Can't handle \"%s\"", analyzedStatement));
        }

        @Override
        public ListenableFuture<Long> visitCreateTableStatement(CreateTableAnalyzedStatement analysis, UUID jobId) {
            return tableCreator.create(analysis);
        }

        @Override
        public ListenableFuture<Long> visitAlterTableStatement(final AlterTableAnalyzedStatement analysis,
                UUID jobId) {
            return alterTableOperation.executeAlterTable(analysis);
        }

        @Override
        public ListenableFuture<Long> visitAddColumnStatement(AddColumnAnalyzedStatement analysis, UUID context) {
            return alterTableOperation.executeAlterTableAddColumn(analysis);
        }

        @Override
        public ListenableFuture<Long> visitOptimizeTableStatement(OptimizeTableAnalyzedStatement analysis,
                UUID jobId) {
            ForceMergeRequest request = new ForceMergeRequest(analysis.indexNames().toArray(new String[0]));

            // Pass parameters to ES request
            request.maxNumSegments(analysis.settings().getAsInt(OptimizeSettings.MAX_NUM_SEGMENTS.name(),
                    ForceMergeRequest.Defaults.MAX_NUM_SEGMENTS));
            request.onlyExpungeDeletes(analysis.settings().getAsBoolean(
                    OptimizeSettings.ONLY_EXPUNGE_DELETES.name(), ForceMergeRequest.Defaults.ONLY_EXPUNGE_DELETES));
            request.flush(analysis.settings().getAsBoolean(OptimizeSettings.FLUSH.name(),
                    ForceMergeRequest.Defaults.FLUSH));

            request.indicesOptions(IndicesOptions.lenientExpandOpen());

            FutureActionListener<ForceMergeResponse, Long> listener = new FutureActionListener<>(
                    Functions.constant((long) analysis.indexNames().size()));
            transportActionProvider.transportForceMergeAction().execute(request, listener);
            return listener;
        }

        @Override
        public ListenableFuture<Long> visitRefreshTableStatement(RefreshTableAnalyzedStatement analysis,
                UUID jobId) {
            if (analysis.indexNames().isEmpty()) {
                return Futures.immediateFuture(null);
            }
            RefreshRequest request = new RefreshRequest(
                    analysis.indexNames().toArray(new String[analysis.indexNames().size()]));
            request.indicesOptions(IndicesOptions.lenientExpandOpen());

            FutureActionListener<RefreshResponse, Long> listener = new FutureActionListener<>(
                    Functions.constant((long) analysis.indexNames().size()));
            transportActionProvider.transportRefreshAction().execute(request, listener);
            return listener;
        }

        @Override
        public ListenableFuture<Long> visitCreateBlobTableStatement(CreateBlobTableAnalyzedStatement analysis,
                UUID jobId) {
            return wrapRowCountFuture(
                    blobIndicesService.createBlobTable(analysis.tableName(), analysis.tableParameter().settings()),
                    1L);
        }

        @Override
        public ListenableFuture<Long> visitAlterBlobTableStatement(AlterBlobTableAnalyzedStatement analysis,
                UUID jobId) {
            return wrapRowCountFuture(blobIndicesService.alterBlobTable(analysis.table().ident().name(),
                    analysis.tableParameter().settings()), 1L);
        }

        @Override
        public ListenableFuture<Long> visitDropBlobTableStatement(DropBlobTableAnalyzedStatement analysis,
                UUID jobId) {
            return wrapRowCountFuture(blobIndicesService.dropBlobTable(analysis.table().ident().name()), 1L);
        }

        @Override
        public ListenableFuture<Long> visitDropRepositoryAnalyzedStatement(DropRepositoryAnalyzedStatement analysis,
                UUID jobId) {
            return repositoryService.execute(analysis);
        }

        @Override
        public ListenableFuture<Long> visitCreateRepositoryAnalyzedStatement(
                CreateRepositoryAnalyzedStatement analysis, UUID jobId) {
            return repositoryService.execute(analysis);
        }

        @Override
        public ListenableFuture<Long> visitDropSnapshotAnalyzedStatement(DropSnapshotAnalyzedStatement analysis,
                UUID jobId) {
            return snapshotRestoreDDLDispatcher.dispatch(analysis);
        }

        public ListenableFuture<Long> visitCreateSnapshotAnalyzedStatement(CreateSnapshotAnalyzedStatement analysis,
                UUID jobId) {
            return snapshotRestoreDDLDispatcher.dispatch(analysis);
        }

        @Override
        public ListenableFuture<Long> visitRestoreSnapshotAnalyzedStatement(
                RestoreSnapshotAnalyzedStatement analysis, UUID context) {
            return snapshotRestoreDDLDispatcher.dispatch(analysis);
        }
    }

    private ListenableFuture<Long> wrapRowCountFuture(ListenableFuture<?> wrappedFuture, final Long rowCount) {
        return Futures.transform(wrappedFuture, new Function<Object, Long>() {
            @Nullable
            @Override
            public Long apply(@Nullable Object input) {
                return rowCount;
            }
        });
    }
}