<commit_before>/*
 * Licensed to STRATIO (C) under one or more contributor license agreements.
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.  The STRATIO (C) 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.
 */

package com.stratio.crossdata.core.planner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.stratio.crossdata.common.data.AlterOperation;
import com.stratio.crossdata.common.data.AlterOptions;
import com.stratio.crossdata.common.data.CatalogName;
import com.stratio.crossdata.common.data.Cell;
import com.stratio.crossdata.common.data.ClusterName;
import com.stratio.crossdata.common.data.ColumnName;
import com.stratio.crossdata.common.data.ConnectorName;
import com.stratio.crossdata.common.data.IndexName;
import com.stratio.crossdata.common.data.Row;
import com.stratio.crossdata.common.data.Status;
import com.stratio.crossdata.common.data.TableName;
import com.stratio.crossdata.common.exceptions.IgnoreQueryException;
import com.stratio.crossdata.common.exceptions.PlanningException;
import com.stratio.crossdata.common.exceptions.ValidationException;
import com.stratio.crossdata.common.executionplan.ExecutionPath;
import com.stratio.crossdata.common.executionplan.ExecutionType;
import com.stratio.crossdata.common.executionplan.ExecutionWorkflow;
import com.stratio.crossdata.common.executionplan.ManagementWorkflow;
import com.stratio.crossdata.common.executionplan.MetadataWorkflow;
import com.stratio.crossdata.common.executionplan.QueryWorkflow;
import com.stratio.crossdata.common.executionplan.ResultType;
import com.stratio.crossdata.common.executionplan.StorageWorkflow;
import com.stratio.crossdata.common.logicalplan.*;
import com.stratio.crossdata.common.manifest.FunctionType;
import com.stratio.crossdata.common.metadata.CatalogMetadata;
import com.stratio.crossdata.common.metadata.ClusterMetadata;
import com.stratio.crossdata.common.metadata.ColumnMetadata;
import com.stratio.crossdata.common.metadata.ColumnType;
import com.stratio.crossdata.common.metadata.ConnectorAttachedMetadata;
import com.stratio.crossdata.common.metadata.ConnectorMetadata;
import com.stratio.crossdata.common.metadata.DataType;
import com.stratio.crossdata.common.metadata.IndexMetadata;
import com.stratio.crossdata.common.metadata.IndexType;
import com.stratio.crossdata.common.metadata.Operations;
import com.stratio.crossdata.common.metadata.TableMetadata;
import com.stratio.crossdata.common.statements.structures.AsteriskSelector;
import com.stratio.crossdata.common.statements.structures.BooleanSelector;
import com.stratio.crossdata.common.statements.structures.ColumnSelector;
import com.stratio.crossdata.common.statements.structures.FloatingPointSelector;
import com.stratio.crossdata.common.statements.structures.FunctionSelector;
import com.stratio.crossdata.common.statements.structures.IntegerSelector;
import com.stratio.crossdata.common.statements.structures.Operator;
import com.stratio.crossdata.common.statements.structures.Relation;
import com.stratio.crossdata.common.statements.structures.SelectExpression;
import com.stratio.crossdata.common.statements.structures.Selector;
import com.stratio.crossdata.common.statements.structures.StringSelector;
import com.stratio.crossdata.common.utils.Constants;
import com.stratio.crossdata.common.utils.StringUtils;
import com.stratio.crossdata.core.metadata.MetadataManager;
import com.stratio.crossdata.core.query.BaseQuery;
import com.stratio.crossdata.core.query.MetadataPlannedQuery;
import com.stratio.crossdata.core.query.MetadataValidatedQuery;
import com.stratio.crossdata.core.query.SelectParsedQuery;
import com.stratio.crossdata.core.query.SelectPlannedQuery;
import com.stratio.crossdata.core.query.SelectValidatedQuery;
import com.stratio.crossdata.core.query.StoragePlannedQuery;
import com.stratio.crossdata.core.query.StorageValidatedQuery;
import com.stratio.crossdata.core.statements.AlterCatalogStatement;
import com.stratio.crossdata.core.statements.AlterClusterStatement;
import com.stratio.crossdata.core.statements.AlterTableStatement;
import com.stratio.crossdata.core.statements.AttachClusterStatement;
import com.stratio.crossdata.core.statements.AttachConnectorStatement;
import com.stratio.crossdata.core.statements.CreateCatalogStatement;
import com.stratio.crossdata.core.statements.CreateIndexStatement;
import com.stratio.crossdata.core.statements.CreateTableStatement;
import com.stratio.crossdata.core.statements.DeleteStatement;
import com.stratio.crossdata.core.statements.DetachClusterStatement;
import com.stratio.crossdata.core.statements.DetachConnectorStatement;
import com.stratio.crossdata.core.statements.DropCatalogStatement;
import com.stratio.crossdata.core.statements.DropIndexStatement;
import com.stratio.crossdata.core.statements.DropTableStatement;
import com.stratio.crossdata.core.statements.ImportMetadataStatement;
import com.stratio.crossdata.core.statements.InsertIntoStatement;
import com.stratio.crossdata.core.statements.MetadataStatement;
import com.stratio.crossdata.core.statements.SelectStatement;
import com.stratio.crossdata.core.statements.TruncateStatement;
import com.stratio.crossdata.core.statements.UpdateTableStatement;
import com.stratio.crossdata.core.structures.InnerJoin;
import com.stratio.crossdata.core.utils.CoreUtils;
import com.stratio.crossdata.core.validator.Validator;

/**
 * Class in charge of defining the set of {@link com.stratio.crossdata.common.logicalplan.LogicalStep}
 * required to execute a statement. This set of steps are ordered as a workflow on a {@link
 * com.stratio.crossdata.common.logicalplan.LogicalWorkflow} structure. Notice that the LogicalWorkflow
 * may contain several initial steps, but it will always finish in a single operation.
 */
public class Planner {

    /**
     * Class logger.
     */
    private static final Logger LOG = Logger.getLogger(Planner.class);

    /**
     * Define a logical workflow that represents the operations required for executing the {@code SELECT} query sent
     * by the user. After that, an ExecutionWorkflow is creating determining which connectors will execute the
     * different elements of the original query.
     *
     * @param query A {@link com.stratio.crossdata.core.query.SelectValidatedQuery}.
     * @return A {@link com.stratio.crossdata.core.query.SelectPlannedQuery}.
     * @throws com.stratio.crossdata.common.exceptions.PlanningException If the query cannot be planned.
     */
    public SelectPlannedQuery planQuery(SelectValidatedQuery query) throws PlanningException {
        query.optimizeQuery();
        LogicalWorkflow workflow = buildWorkflow(query);
        //Add the sql direct query to the logical workflow.
        workflow.setSqlDirectQuery(query.getStatement().toSQLString());
        //Plan the workflow execution into different connectors.
        ExecutionWorkflow executionWorkflow = buildExecutionWorkflow(query.getQueryId(), workflow);
        //Return the planned query.
        return new SelectPlannedQuery(query, executionWorkflow);
    }

    /**
     * Define an execution plan for metadata queries.
     *
     * @param query A {@link com.stratio.crossdata.core.query.MetadataValidatedQuery}.
     * @return A {@link com.stratio.crossdata.core.query.MetadataPlannedQuery}.
     * @throws PlanningException If the query cannot be planned.
     */
    public MetadataPlannedQuery planQuery(MetadataValidatedQuery query) throws PlanningException {
        ExecutionWorkflow executionWorkflow = buildExecutionWorkflow(query);
        return new MetadataPlannedQuery(query, executionWorkflow);
    }

    /**
     * Define an execution plan for storage queries.
     *
     * @param query A {@link com.stratio.crossdata.core.query.StorageValidatedQuery}.
     * @return A {@link com.stratio.crossdata.core.query.StoragePlannedQuery}.
     * @throws PlanningException If the query cannot be planned.
     */
    public StoragePlannedQuery planQuery(StorageValidatedQuery query) throws PlanningException {
        ExecutionWorkflow executionWorkflow = buildExecutionWorkflow(query);
        return new StoragePlannedQuery(query, executionWorkflow);
    }

    /**
     * Build a execution workflow for a query analyzing the existing logical workflow.
     *
     * @param queryId  The query identifier.<commit_msg>Fix: SQLDirectQuery was missing at 'planQuery' in Planner after building execution workflow.<commit_after>/*
 * Licensed to STRATIO (C) under one or more contributor license agreements.
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.  The STRATIO (C) 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.
 */

package com.stratio.crossdata.core.planner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.stratio.crossdata.common.data.AlterOperation;
import com.stratio.crossdata.common.data.AlterOptions;
import com.stratio.crossdata.common.data.CatalogName;
import com.stratio.crossdata.common.data.Cell;
import com.stratio.crossdata.common.data.ClusterName;
import com.stratio.crossdata.common.data.ColumnName;
import com.stratio.crossdata.common.data.ConnectorName;
import com.stratio.crossdata.common.data.IndexName;
import com.stratio.crossdata.common.data.Row;
import com.stratio.crossdata.common.data.Status;
import com.stratio.crossdata.common.data.TableName;
import com.stratio.crossdata.common.exceptions.IgnoreQueryException;
import com.stratio.crossdata.common.exceptions.PlanningException;
import com.stratio.crossdata.common.exceptions.ValidationException;
import com.stratio.crossdata.common.executionplan.ExecutionPath;
import com.stratio.crossdata.common.executionplan.ExecutionType;
import com.stratio.crossdata.common.executionplan.ExecutionWorkflow;
import com.stratio.crossdata.common.executionplan.ManagementWorkflow;
import com.stratio.crossdata.common.executionplan.MetadataWorkflow;
import com.stratio.crossdata.common.executionplan.QueryWorkflow;
import com.stratio.crossdata.common.executionplan.ResultType;
import com.stratio.crossdata.common.executionplan.StorageWorkflow;
import com.stratio.crossdata.common.logicalplan.*;
import com.stratio.crossdata.common.manifest.FunctionType;
import com.stratio.crossdata.common.metadata.CatalogMetadata;
import com.stratio.crossdata.common.metadata.ClusterMetadata;
import com.stratio.crossdata.common.metadata.ColumnMetadata;
import com.stratio.crossdata.common.metadata.ColumnType;
import com.stratio.crossdata.common.metadata.ConnectorAttachedMetadata;
import com.stratio.crossdata.common.metadata.ConnectorMetadata;
import com.stratio.crossdata.common.metadata.DataType;
import com.stratio.crossdata.common.metadata.IndexMetadata;
import com.stratio.crossdata.common.metadata.IndexType;
import com.stratio.crossdata.common.metadata.Operations;
import com.stratio.crossdata.common.metadata.TableMetadata;
import com.stratio.crossdata.common.statements.structures.AsteriskSelector;
import com.stratio.crossdata.common.statements.structures.BooleanSelector;
import com.stratio.crossdata.common.statements.structures.ColumnSelector;
import com.stratio.crossdata.common.statements.structures.FloatingPointSelector;
import com.stratio.crossdata.common.statements.structures.FunctionSelector;
import com.stratio.crossdata.common.statements.structures.IntegerSelector;
import com.stratio.crossdata.common.statements.structures.Operator;
import com.stratio.crossdata.common.statements.structures.Relation;
import com.stratio.crossdata.common.statements.structures.SelectExpression;
import com.stratio.crossdata.common.statements.structures.Selector;
import com.stratio.crossdata.common.statements.structures.StringSelector;
import com.stratio.crossdata.common.utils.Constants;
import com.stratio.crossdata.common.utils.StringUtils;
import com.stratio.crossdata.core.metadata.MetadataManager;
import com.stratio.crossdata.core.query.BaseQuery;
import com.stratio.crossdata.core.query.MetadataPlannedQuery;
import com.stratio.crossdata.core.query.MetadataValidatedQuery;
import com.stratio.crossdata.core.query.SelectParsedQuery;
import com.stratio.crossdata.core.query.SelectPlannedQuery;
import com.stratio.crossdata.core.query.SelectValidatedQuery;
import com.stratio.crossdata.core.query.StoragePlannedQuery;
import com.stratio.crossdata.core.query.StorageValidatedQuery;
import com.stratio.crossdata.core.statements.AlterCatalogStatement;
import com.stratio.crossdata.core.statements.AlterClusterStatement;
import com.stratio.crossdata.core.statements.AlterTableStatement;
import com.stratio.crossdata.core.statements.AttachClusterStatement;
import com.stratio.crossdata.core.statements.AttachConnectorStatement;
import com.stratio.crossdata.core.statements.CreateCatalogStatement;
import com.stratio.crossdata.core.statements.CreateIndexStatement;
import com.stratio.crossdata.core.statements.CreateTableStatement;
import com.stratio.crossdata.core.statements.DeleteStatement;
import com.stratio.crossdata.core.statements.DetachClusterStatement;
import com.stratio.crossdata.core.statements.DetachConnectorStatement;
import com.stratio.crossdata.core.statements.DropCatalogStatement;
import com.stratio.crossdata.core.statements.DropIndexStatement;
import com.stratio.crossdata.core.statements.DropTableStatement;
import com.stratio.crossdata.core.statements.ImportMetadataStatement;
import com.stratio.crossdata.core.statements.InsertIntoStatement;
import com.stratio.crossdata.core.statements.MetadataStatement;
import com.stratio.crossdata.core.statements.SelectStatement;
import com.stratio.crossdata.core.statements.TruncateStatement;
import com.stratio.crossdata.core.statements.UpdateTableStatement;
import com.stratio.crossdata.core.structures.InnerJoin;
import com.stratio.crossdata.core.utils.CoreUtils;
import com.stratio.crossdata.core.validator.Validator;

/**
 * Class in charge of defining the set of {@link com.stratio.crossdata.common.logicalplan.LogicalStep}
 * required to execute a statement. This set of steps are ordered as a workflow on a {@link
 * com.stratio.crossdata.common.logicalplan.LogicalWorkflow} structure. Notice that the LogicalWorkflow
 * may contain several initial steps, but it will always finish in a single operation.
 */
public class Planner {

    /**
     * Class logger.
     */
    private static final Logger LOG = Logger.getLogger(Planner.class);

    /**
     * Define a logical workflow that represents the operations required for executing the {@code SELECT} query sent
     * by the user. After that, an ExecutionWorkflow is creating determining which connectors will execute the
     * different elements of the original query.
     *
     * @param query A {@link com.stratio.crossdata.core.query.SelectValidatedQuery}.
     * @return A {@link com.stratio.crossdata.core.query.SelectPlannedQuery}.
     * @throws com.stratio.crossdata.common.exceptions.PlanningException If the query cannot be planned.
     */
    public SelectPlannedQuery planQuery(SelectValidatedQuery query) throws PlanningException {
        query.optimizeQuery();
        LogicalWorkflow workflow = buildWorkflow(query);
        //Plan the workflow execution into different connectors.
        ExecutionWorkflow executionWorkflow = buildExecutionWorkflow(query.getQueryId(), workflow);
        //Return the planned query.
        SelectPlannedQuery plannedQuery = new SelectPlannedQuery(query, executionWorkflow);
        //Add the sql direct query to the logical workflow.
        String sqlQuery = query.getStatement().toSQLString();
        ((QueryWorkflow)plannedQuery
                .getExecutionWorkflow())
                .getWorkflow()
                .setSqlDirectQuery(query.getStatement().toSQLString());
        return plannedQuery;
    }

    /**
     * Define an execution plan for metadata queries.
     *
     * @param query A {@link com.stratio.crossdata.core.query.MetadataValidatedQuery}.
     * @return A {@link com.stratio.crossdata.core.query.MetadataPlannedQuery}.
     * @throws PlanningException If the query cannot be planned.
     */
    public MetadataPlannedQuery planQuery(MetadataValidatedQuery query) throws PlanningException {
        ExecutionWorkflow executionWorkflow = buildExecutionWorkflow(query);
        return new MetadataPlannedQuery(query, executionWorkflow);
    }

    /**
     * Define an execution plan for storage queries.
     *
     * @param query A {@link com.stratio.crossdata.core.query.StorageValidatedQuery}.
     * @return A {@link com.stratio.crossdata.core.query.StoragePlannedQuery}.
     * @throws PlanningException If the query cannot be planned.
     */
    public StoragePlannedQuery planQuery(StorageValidatedQuery query) throws PlanningException {
        ExecutionWorkflow executionWorkflow = buildExecutionWorkflow(query);
        return new StoragePlannedQuery(query, executionWorkflow);
    }

    /**
     * Build a execution workflow for a query analyzing the existing logical workflow.
     *
     * @param queryId  The query identifier.
{'fraction_non_alphanumeric': 0.08881261396546176, 'fraction_numerical': 0.0005363080553469913, 'mean_word_length': 5.211525649566956, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5454168', 'n_tokens_mistral': 5184, 'n_tokens_neox': 5062, 'n_words': 1103}