
org.neo4j.cypher.internal.compiler.phases.LogicalPlanState.scala Maven / Gradle / Ivy
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.cypher.internal.compiler.phases
import org.neo4j.configuration.GraphDatabaseInternalSettings.RemoteBatchPropertiesImplementation
import org.neo4j.cypher.internal.ast.Query
import org.neo4j.cypher.internal.ast.Statement
import org.neo4j.cypher.internal.ast.semantics.CachableSemanticTable
import org.neo4j.cypher.internal.ast.semantics.SemanticState
import org.neo4j.cypher.internal.ast.semantics.SemanticTable
import org.neo4j.cypher.internal.expressions.AutoExtractedParameter
import org.neo4j.cypher.internal.expressions.Expression
import org.neo4j.cypher.internal.frontend.PlannerName
import org.neo4j.cypher.internal.frontend.phases.BaseState
import org.neo4j.cypher.internal.ir.PlannerQuery
import org.neo4j.cypher.internal.logical.plans.LogicalPlan
import org.neo4j.cypher.internal.options.CypherEagerAnalyzerOption
import org.neo4j.cypher.internal.planner.spi.ImmutablePlanningAttribute
import org.neo4j.cypher.internal.planner.spi.ImmutablePlanningAttributes
import org.neo4j.cypher.internal.planner.spi.PlanningAttributes
import org.neo4j.cypher.internal.planner.spi.PlanningAttributes.CachedPropertiesPerPlan
import org.neo4j.cypher.internal.planner.spi.PlanningAttributes.LabelAndRelTypeInfos
import org.neo4j.cypher.internal.planner.spi.PlanningAttributesCacheKey
import org.neo4j.cypher.internal.util.AnonymousVariableNameGenerator
import org.neo4j.cypher.internal.util.ObfuscationMetadata
import org.neo4j.cypher.internal.util.StepSequencer
import org.neo4j.cypher.internal.util.attribution.Attribute
import org.neo4j.cypher.internal.util.attribution.PartialAttribute
/*
This is the state that is used during query compilation. It accumulates more and more values as it passes through
the compiler pipe line, finally ending up containing a logical plan.
Normally, it is created with only the first three params as given, and the rest is built up while passing through
the pipe line
*/
case class LogicalPlanState(
queryText: String,
plannerName: PlannerName,
planningAttributes: PlanningAttributes,
anonymousVariableNameGenerator: AnonymousVariableNameGenerator,
maybeProcedureSignatureVersion: Option[Long] = None,
maybeStatement: Option[Statement] = None,
maybeSemantics: Option[SemanticState] = None,
maybeExtractedParams: Option[Map[AutoExtractedParameter, Expression]] = None,
maybeSemanticTable: Option[SemanticTable] = None,
maybeQuery: Option[PlannerQuery] = None,
maybeLogicalPlan: Option[LogicalPlan] = None,
accumulatedConditions: Set[StepSequencer.Condition] = Set.empty,
hasLoadCSV: Boolean = false,
maybeReturnColumns: Option[Seq[String]] = None,
maybeObfuscationMetadata: Option[ObfuscationMetadata] = None,
maybeEagerAnalyzerOption: Option[CypherEagerAnalyzerOption] = None,
maybeRemoteBatchPropertiesImplementation: Option[RemoteBatchPropertiesImplementation] = None
) extends BaseState {
def query: PlannerQuery = maybeQuery getOrElse fail("The planner query")
def logicalPlan: LogicalPlan = maybeLogicalPlan getOrElse fail("Logical plan")
def astAsQuery: Query = statement().asInstanceOf[Query]
def asCachableLogicalPlanState(): CachableLogicalPlanState = {
CachableLogicalPlanState(
queryText,
plannerName,
CachablePlanningAttributes(
ImmutablePlanningAttributes.EffectiveCardinalities(planningAttributes.effectiveCardinalities),
ImmutablePlanningAttributes.ProvidedOrders(planningAttributes.providedOrders),
ImmutablePlanningAttributes.LeveragedOrders(planningAttributes.leveragedOrders),
planningAttributes.labelAndRelTypeInfos,
planningAttributes.cachedPropertiesPerPlan,
planningAttributes.solveds.getOption(logicalPlan.id).exists(_.readOnly)
),
anonymousVariableNameGenerator,
statement(),
CachableSemanticTable(semanticTable()),
logicalPlan,
hasLoadCSV,
returnColumns()
)
}
override def withStatement(s: Statement): LogicalPlanState = copy(maybeStatement = Some(s))
override def withReturnColumns(cols: Seq[String]): LogicalPlanState = copy(maybeReturnColumns = Some(cols))
override def withSemanticTable(s: SemanticTable): LogicalPlanState = copy(maybeSemanticTable = Some(s))
override def withSemanticState(s: SemanticState): LogicalPlanState = copy(maybeSemantics = Some(s))
override def withParams(p: Map[AutoExtractedParameter, Expression]): LogicalPlanState =
copy(maybeExtractedParams = Some(p))
override def withObfuscationMetadata(o: ObfuscationMetadata): LogicalPlanState =
copy(maybeObfuscationMetadata = Some(o))
def withMaybeLogicalPlan(p: Option[LogicalPlan]): LogicalPlanState = copy(maybeLogicalPlan = p)
def withMaybeQuery(q: Option[PlannerQuery]): LogicalPlanState = copy(maybeQuery = q)
def withNewPlanningAttributes(attributes: PlanningAttributes): LogicalPlanState =
copy(planningAttributes = attributes)
override def withProcedureSignatureVersion(generation: Option[Long]): LogicalPlanState =
copy(maybeProcedureSignatureVersion = generation)
def withRemoteBatchPropertiesImplementation(remoteBatchPropertiesImplementation: RemoteBatchPropertiesImplementation)
: LogicalPlanState = copy(maybeRemoteBatchPropertiesImplementation = Some(remoteBatchPropertiesImplementation))
}
object LogicalPlanState {
def apply(state: BaseState): LogicalPlanState =
LogicalPlanState(
queryText = state.queryText,
plannerName = state.plannerName,
planningAttributes = PlanningAttributes.newAttributes,
maybeProcedureSignatureVersion = state.maybeProcedureSignatureVersion,
maybeStatement = state.maybeStatement,
maybeSemantics = state.maybeSemantics,
maybeExtractedParams = state.maybeExtractedParams,
maybeSemanticTable = state.maybeSemanticTable,
accumulatedConditions = state.accumulatedConditions,
maybeReturnColumns = state.maybeReturnColumns,
maybeObfuscationMetadata = state.maybeObfuscationMetadata,
anonymousVariableNameGenerator = state.anonymousVariableNameGenerator
)
}
/**
* A subset of the data stored in LogicalPlanState.
*/
case class CachableLogicalPlanState(
queryText: String,
plannerName: PlannerName,
planningAttributes: CachablePlanningAttributes,
anonymousVariableNameGenerator: AnonymousVariableNameGenerator,
statement: Statement,
semanticTable: CachableSemanticTable,
logicalPlan: LogicalPlan,
hasLoadCSV: Boolean = false,
returnColumns: Seq[String]
)
case class CachablePlanningAttributes(
effectiveCardinalities: ImmutablePlanningAttributes.EffectiveCardinalities,
providedOrders: ImmutablePlanningAttributes.ProvidedOrders,
leveragedOrders: ImmutablePlanningAttributes.LeveragedOrders,
labelAndRelTypeInfos: LabelAndRelTypeInfos,
cachedPropertiesPerPlan: CachedPropertiesPerPlan,
readOnly: Boolean
) {
def cacheKey: PlanningAttributesCacheKey =
PlanningAttributesCacheKey(
effectiveCardinalities,
providedOrders,
leveragedOrders
)
// Let's not override the copy method of case classes
def createCopy(): CachablePlanningAttributes =
CachablePlanningAttributes(
effectiveCardinalities, // Immutable
providedOrders, // Immutable
leveragedOrders, // Immutable
labelAndRelTypeInfos.clone[LabelAndRelTypeInfos],
cachedPropertiesPerPlan.clone[CachedPropertiesPerPlan],
readOnly
)
def hasEqualSizeAttributes: Boolean = {
productIterator
.collect {
case a: Attribute[_, _] if !a.isInstanceOf[PartialAttribute[_, _]] => a.size
case a: ImmutablePlanningAttribute[_] => a.size
}
.distinct
.size == 1
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy