<commit_before>/**
 * Copyright (c) 2002-2014 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.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 <http://www.gnu.org/licenses/>.
 */
package org.neo4j.cypher.internal

import org.neo4j.cypher._
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.graphdb.factory.GraphDatabaseSettings
import org.neo4j.kernel.{GraphDatabaseAPI, InternalAbstractGraphDatabase}
import org.neo4j.cypher.internal.compiler.v2_1.{CypherCompilerFactory => CypherCompilerFactory2_1}
import org.neo4j.cypher.internal.compiler.v2_0.{CypherCompiler => CypherCompiler2_0}
import org.neo4j.cypher.internal.compiler.v1_9.{CypherCompiler => CypherCompiler1_9}
import org.neo4j.cypher.internal.compiler.v2_1.executionplan.{ExecutionPlan => ExecutionPlan_v2_1}
import org.neo4j.cypher.internal.compiler.v2_0.executionplan.{ExecutionPlan => ExecutionPlan_v2_0}
import org.neo4j.cypher.internal.compiler.v1_9.executionplan.{ExecutionPlan => ExecutionPlan_v1_9}
import org.neo4j.cypher.internal.spi.v2_1.{TransactionBoundQueryContext => QueryContext_v2_1}
import org.neo4j.cypher.internal.spi.v2_0.{TransactionBoundQueryContext => QueryContext_v2_0}
import org.neo4j.cypher.internal.spi.v1_9.{GDSBackedQueryContext => QueryContext_v1_9}
import org.neo4j.cypher.internal.spi.v2_1.{TransactionBoundPlanContext => PlanContext_v2_1}
import org.neo4j.cypher.internal.spi.v2_0.{TransactionBoundPlanContext => PlanContext_v2_0}
import org.neo4j.cypher.internal.compiler.v2_1.spi.{ExceptionTranslatingQueryContext => ExceptionTranslatingQueryContext_v2_1}
import org.neo4j.cypher.internal.compiler.v2_0.spi.{ExceptionTranslatingQueryContext => ExceptionTranslatingQueryContext_v2_0}
import org.neo4j.kernel.api.{KernelAPI, Statement}
import org.neo4j.kernel.monitoring.{Monitors=>KernelMonitors}

object CypherCompiler {
  val DEFAULT_QUERY_CACHE_SIZE: Int = 128

  private val hasVersionDefined = """(?si)^\s*cypher\s*([^\s]+)\s*(.*)""".r
}

class CypherCompiler(graph: GraphDatabaseService,
                     kernelAPI: KernelAPI,
                     kernelMonitors: KernelMonitors,
                     defaultVersion: CypherVersion = CypherVersion.vDefault) {

  private val queryCacheSize: Int = getQueryCacheSize

  private val queryCache2_0 = new LRUCache[Object, Object](queryCacheSize)
  private val queryCache1_9 = new LRUCache[String, Object](queryCacheSize)

  val ronjaCompiler2_1 = CypherCompilerFactory2_1.ronjaCompiler(graph, queryCacheSize, kernelMonitors)
  val legacyCompiler2_1 = CypherCompilerFactory2_1.legacyCompiler(graph, queryCacheSize, kernelMonitors)
  val compiler2_0 = new CypherCompiler2_0(graph, (q, f) => queryCache2_0.getOrElseUpdate(q, f))
  val compiler1_9 = new CypherCompiler1_9(graph, (q, f) => queryCache1_9.getOrElseUpdate(q, f))

  @throws(classOf[SyntaxException])
  def prepareQuery(queryText: String): PreparedQuery = {
    val (version, remainingQueryText) = versionedQuery(queryText)

    version match {
      case CypherVersion.experimental =>
        val preparedQueryForV_experimental = ronjaCompiler2_1.prepareQuery(remainingQueryText)
        new PreparedQuery(queryText, version) {
          def isPeriodicCommit = preparedQueryForV_experimental.isPeriodicCommit
          def plan(context: GraphDatabaseService, statement: Statement) = {
            val planContext = new PlanContext_v2_1(statement, kernelAPI, context)
            val (planImpl, extractedParameters) = ronjaCompiler2_1.planPreparedQuery(preparedQueryForV_experimental, planContext)
            (new ExecutionPlanWrapperForV2_1( planImpl ), extractedParameters)
          }
        }

      case CypherVersion.v2_1 =>
        new PreparedQuery(queryText, version) {
          val preparedQueryForV_2_1 = ronjaCompiler2_1.prepareQuery(remainingQueryText)
          override def plan(context: GraphDatabaseService, statement: Statement): (ExecutionPlan, Map[String, Any]) = {
            val planContext = new PlanContext_v2_1(statement, kernelAPI, context)
            val (planImpl, extractedParameters) = legacyCompiler2_1.planPreparedQuery(preparedQueryForV_2_1, planContext)
            (new ExecutionPlanWrapperForV2_1( planImpl ), extractedParameters)
          }

          override def isPeriodicCommit: Boolean = preparedQueryForV_2_1.isPeriodicCommit
        }

      case CypherVersion.v2_0 =>
        new PreparedQuery(queryText, version) {
          override def plan(context: GraphDatabaseService, statement: Statement): (ExecutionPlan, Map[String, Any]) = {
            val planImpl = compiler2_0.prepare(remainingQueryText, new PlanContext_v2_0(statement, context))
            (new ExecutionPlanWrapperForV2_0(planImpl), Map.empty)
          }

          override def isPeriodicCommit: Boolean = false
        }

      case CypherVersion.v1_9 =>
        new PreparedQuery(queryText, version) {
          override def plan(context: GraphDatabaseService, statement: Statement): (ExecutionPlan, Map[String, Any]) = {
            val planImpl = compiler1_9.prepare(remainingQueryText)
            (new ExecutionPlanWrapperForV1_9(planImpl), Map.empty)
          }
<commit_msg>Make sure the isPeriodicCommit check works gracefully for invalid queries<commit_after>/**
 * Copyright (c) 2002-2014 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.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 <http://www.gnu.org/licenses/>.
 */
package org.neo4j.cypher.internal

import org.neo4j.cypher._
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.graphdb.factory.GraphDatabaseSettings
import org.neo4j.kernel.{GraphDatabaseAPI, InternalAbstractGraphDatabase}
import org.neo4j.cypher.internal.compiler.v2_1.{CypherCompilerFactory => CypherCompilerFactory2_1}
import org.neo4j.cypher.internal.compiler.v2_0.{CypherCompiler => CypherCompiler2_0}
import org.neo4j.cypher.internal.compiler.v1_9.{CypherCompiler => CypherCompiler1_9}
import org.neo4j.cypher.internal.compiler.v2_1.executionplan.{ExecutionPlan => ExecutionPlan_v2_1}
import org.neo4j.cypher.internal.compiler.v2_0.executionplan.{ExecutionPlan => ExecutionPlan_v2_0}
import org.neo4j.cypher.internal.compiler.v1_9.executionplan.{ExecutionPlan => ExecutionPlan_v1_9}
import org.neo4j.cypher.internal.spi.v2_1.{TransactionBoundQueryContext => QueryContext_v2_1}
import org.neo4j.cypher.internal.spi.v2_0.{TransactionBoundQueryContext => QueryContext_v2_0}
import org.neo4j.cypher.internal.spi.v1_9.{GDSBackedQueryContext => QueryContext_v1_9}
import org.neo4j.cypher.internal.spi.v2_1.{TransactionBoundPlanContext => PlanContext_v2_1}
import org.neo4j.cypher.internal.spi.v2_0.{TransactionBoundPlanContext => PlanContext_v2_0}
import org.neo4j.cypher.internal.compiler.v2_1.spi.{ExceptionTranslatingQueryContext => ExceptionTranslatingQueryContext_v2_1}
import org.neo4j.cypher.internal.compiler.v2_0.spi.{ExceptionTranslatingQueryContext => ExceptionTranslatingQueryContext_v2_0}
import org.neo4j.kernel.api.{KernelAPI, Statement}
import org.neo4j.kernel.monitoring.{Monitors=>KernelMonitors}

import scala.util.Try

object CypherCompiler {
  val DEFAULT_QUERY_CACHE_SIZE: Int = 128

  private val hasVersionDefined = """(?si)^\s*cypher\s*([^\s]+)\s*(.*)""".r
}

class CypherCompiler(graph: GraphDatabaseService,
                     kernelAPI: KernelAPI,
                     kernelMonitors: KernelMonitors,
                     defaultVersion: CypherVersion = CypherVersion.vDefault) {

  private val queryCacheSize: Int = getQueryCacheSize

  private val queryCache2_0 = new LRUCache[Object, Object](queryCacheSize)
  private val queryCache1_9 = new LRUCache[String, Object](queryCacheSize)

  val ronjaCompiler2_1 = CypherCompilerFactory2_1.ronjaCompiler(graph, queryCacheSize, kernelMonitors)
  val legacyCompiler2_1 = CypherCompilerFactory2_1.legacyCompiler(graph, queryCacheSize, kernelMonitors)
  val compiler2_0 = new CypherCompiler2_0(graph, (q, f) => queryCache2_0.getOrElseUpdate(q, f))
  val compiler1_9 = new CypherCompiler1_9(graph, (q, f) => queryCache1_9.getOrElseUpdate(q, f))

  @throws(classOf[SyntaxException])
  def prepareQuery(queryText: String): PreparedQuery = {
    val (version, remainingQueryText) = versionedQuery(queryText)

    version match {
      case CypherVersion.experimental =>
        val preparedQueryForV_experimental = Try(ronjaCompiler2_1.prepareQuery(remainingQueryText))
        new PreparedQuery(queryText, version) {
          def isPeriodicCommit = preparedQueryForV_experimental.map(_.isPeriodicCommit).getOrElse(false)
          def plan(context: GraphDatabaseService, statement: Statement) = {
            val planContext = new PlanContext_v2_1(statement, kernelAPI, context)
            val (planImpl, extractedParameters) = ronjaCompiler2_1.planPreparedQuery(preparedQueryForV_experimental.get, planContext)
            (new ExecutionPlanWrapperForV2_1( planImpl ), extractedParameters)
          }
        }

      case CypherVersion.v2_1 =>
        new PreparedQuery(queryText, version) {
          val preparedQueryForV_2_1 = Try(ronjaCompiler2_1.prepareQuery(remainingQueryText))
          override def plan(context: GraphDatabaseService, statement: Statement): (ExecutionPlan, Map[String, Any]) = {
            val planContext = new PlanContext_v2_1(statement, kernelAPI, context)
            val (planImpl, extractedParameters) = legacyCompiler2_1.planPreparedQuery(preparedQueryForV_2_1.get, planContext)
            (new ExecutionPlanWrapperForV2_1( planImpl ), extractedParameters)
          }

          override def isPeriodicCommit: Boolean = preparedQueryForV_2_1.map(_.isPeriodicCommit).getOrElse(false)
        }

      case CypherVersion.v2_0 =>
        new PreparedQuery(queryText, version) {
          override def plan(context: GraphDatabaseService, statement: Statement): (ExecutionPlan, Map[String, Any]) = {
            val planImpl = compiler2_0.prepare(remainingQueryText, new PlanContext_v2_0(statement, context))
            (new ExecutionPlanWrapperForV2_0(planImpl), Map.empty)
          }

          override def isPeriodicCommit: Boolean = false
        }

      case CypherVersion.v1_9 =>
        new PreparedQuery(queryText, version) {
          override def plan(context: GraphDatabaseService, statement: Statement): (ExecutionPlan, Map[String, Any]) = {
            val planImpl = compiler1_9.prepare(remainingQueryText)
            (new ExecutionPlanWrapperForV1_9(planImpl), Map.empty)
          }

{'fraction_non_alphanumeric': 0.08812687526789541, 'fraction_numerical': 0.025375053579082728, 'mean_word_length': 4.474425152510558, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 45, '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': '4268067', 'n_tokens_mistral': 3637, 'n_tokens_neox': 3489, 'n_words': 737}