Skip to content

Commit

Permalink
Split SchemaRuleNotFoundException to more specific exceptions, introd…
Browse files Browse the repository at this point in the history
…uce hierarchy of exceptions for duplicate schema rules. Provide tests for expected user messages.
  • Loading branch information
MishaDemianenko committed Jul 26, 2015
1 parent aa6ca0d commit 12c003f
Show file tree
Hide file tree
Showing 18 changed files with 663 additions and 80 deletions.
Expand Up @@ -26,7 +26,7 @@ import org.neo4j.kernel.GraphDatabaseAPI
import org.neo4j.kernel.api.Statement import org.neo4j.kernel.api.Statement
import org.neo4j.kernel.api.constraints.UniquenessConstraint import org.neo4j.kernel.api.constraints.UniquenessConstraint
import org.neo4j.kernel.api.exceptions.KernelException import org.neo4j.kernel.api.exceptions.KernelException
import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException import org.neo4j.kernel.api.exceptions.schema.SchemaKernelException
import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState}
import org.neo4j.kernel.impl.transaction.log.TransactionIdStore import org.neo4j.kernel.impl.transaction.log.TransactionIdStore


Expand All @@ -49,7 +49,7 @@ class TransactionBoundPlanContext(someStatement: Statement, val gdb: GraphDataba
} }


private def evalOrNone[T](f: => Option[T]): Option[T] = private def evalOrNone[T](f: => Option[T]): Option[T] =
try { f } catch { case _: SchemaRuleNotFoundException => None } try { f } catch { case _: SchemaKernelException => None }


private def getOnlineIndex(descriptor: IndexDescriptor): Option[IndexDescriptor] = private def getOnlineIndex(descriptor: IndexDescriptor): Option[IndexDescriptor] =
statement.readOperations().indexGetState(descriptor) match { statement.readOperations().indexGetState(descriptor) match {
Expand Down
Expand Up @@ -26,7 +26,7 @@ import org.neo4j.kernel.GraphDatabaseAPI
import org.neo4j.kernel.api.Statement import org.neo4j.kernel.api.Statement
import org.neo4j.kernel.api.constraints.UniquenessConstraint import org.neo4j.kernel.api.constraints.UniquenessConstraint
import org.neo4j.kernel.api.exceptions.KernelException import org.neo4j.kernel.api.exceptions.KernelException
import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException import org.neo4j.kernel.api.exceptions.schema.SchemaKernelException
import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState}
import org.neo4j.kernel.impl.transaction.log.TransactionIdStore import org.neo4j.kernel.impl.transaction.log.TransactionIdStore


Expand All @@ -49,7 +49,7 @@ class TransactionBoundPlanContext(initialStatement: Statement, val gdb: GraphDat
} }


private def evalOrNone[T](f: => Option[T]): Option[T] = private def evalOrNone[T](f: => Option[T]): Option[T] =
try { f } catch { case _: SchemaRuleNotFoundException => None } try { f } catch { case _: SchemaKernelException => None }


private def getOnlineIndex(descriptor: IndexDescriptor): Option[IndexDescriptor] = private def getOnlineIndex(descriptor: IndexDescriptor): Option[IndexDescriptor] =
statement.readOperations().indexGetState(descriptor) match { statement.readOperations().indexGetState(descriptor) match {
Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.PropertyConstraint;
import org.neo4j.kernel.api.constraints.RelationshipPropertyConstraint; import org.neo4j.kernel.api.constraints.RelationshipPropertyConstraint;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.schema.DuplicateIndexSchemaRuleException;
import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException;
import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.index.IndexDescriptor;
import org.neo4j.kernel.api.index.InternalIndexState; import org.neo4j.kernel.api.index.InternalIndexState;
Expand All @@ -43,7 +44,7 @@ IndexDescriptor indexesGetForLabelAndPropertyKey( int labelId, int propertyKey )


/** Returns the constraint index for the given labelId and propertyKey. */ /** Returns the constraint index for the given labelId and propertyKey. */
IndexDescriptor uniqueIndexGetForLabelAndPropertyKey( int labelId, int propertyKeyId ) IndexDescriptor uniqueIndexGetForLabelAndPropertyKey( int labelId, int propertyKeyId )
throws SchemaRuleNotFoundException; throws SchemaRuleNotFoundException, DuplicateIndexSchemaRuleException;


/** Get all constraint indexes for a label. */ /** Get all constraint indexes for a label. */
Iterator<IndexDescriptor> uniqueIndexesGetForLabel( int labelId ); Iterator<IndexDescriptor> uniqueIndexesGetForLabel( int labelId );
Expand Down
Expand Up @@ -209,6 +209,7 @@ enum Schema implements Status
NoSuchPropertyKey( DatabaseError, "The request accessed a property that does not exist." ), NoSuchPropertyKey( DatabaseError, "The request accessed a property that does not exist." ),
NoSuchRelationshipType( DatabaseError, "The request accessed a relationship type that does not exist." ), NoSuchRelationshipType( DatabaseError, "The request accessed a relationship type that does not exist." ),
NoSuchSchemaRule( DatabaseError, "The request referred to a schema rule that does not exist." ), NoSuchSchemaRule( DatabaseError, "The request referred to a schema rule that does not exist." ),
DuplicateSchemaRule( DatabaseError, "The request referred to a schema rule that defined multiple times." ),


LabelLimitReached( ClientError, "The maximum number of labels supported has been reached, no more labels can be created." ), LabelLimitReached( ClientError, "The maximum number of labels supported has been reached, no more labels can be created." ),
IndexLimitReached( ClientError, "The maximum number of index entries supported has been reached, no more entities can be indexed." ), IndexLimitReached( ClientError, "The maximum number of index entries supported has been reached, no more entities can be indexed." ),
Expand Down
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2002-2015 "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.kernel.api.exceptions.schema;

import org.neo4j.kernel.api.EntityType;
import org.neo4j.kernel.api.TokenNameLookup;

import static java.lang.String.format;

public class DuplicateEntitySchemaRuleException extends DuplicateSchemaRuleException
{
private static final String DUPLICATE_NODE_RULE_MESSAGE_TEMPLATE =
"Multiple %s found for label '%s' and property '%s'.";
private static final String DUPLICATED_RELATIONSHIP_RULE_MESSAGE_TEMPLATE =
"Multiple %s found for relationship type '%s' and property '%s'.";

private EntityType entityType;

public DuplicateEntitySchemaRuleException( EntityType entityType, int entityId, int propertyKeyId )
{
this( entityType, entityId, propertyKeyId, false );
}

public DuplicateEntitySchemaRuleException( EntityType entityType, int ruleEntityId, int propertyKeyId,
boolean unique )
{
super( getMessageTemplate( entityType ), ruleEntityId, propertyKeyId,
unique ? UNIQUE_CONSTRAINT_PREFIX : CONSTRAINT_PREFIX );
this.entityType = entityType;
}


@Override
public String getUserMessage( TokenNameLookup tokenNameLookup )
{
String entityName = EntityType.NODE == entityType ? tokenNameLookup.labelGetName( ruleEntityId ) :
tokenNameLookup.relationshipTypeGetName( ruleEntityId );
return format( messageTemplate, messagePrefix, entityName,
tokenNameLookup.propertyKeyGetName( propertyKeyId ) );
}

private static String getMessageTemplate( EntityType entityType )
{
switch ( entityType )
{
case NODE:
return DUPLICATE_NODE_RULE_MESSAGE_TEMPLATE;
case RELATIONSHIP:
return DUPLICATED_RELATIONSHIP_RULE_MESSAGE_TEMPLATE;
default:
throw new IllegalArgumentException( "Schema rules for specified entityType not supported." );
}
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2002-2015 "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.kernel.api.exceptions.schema;

import org.neo4j.kernel.api.TokenNameLookup;

import static java.lang.String.format;

public class DuplicateIndexSchemaRuleException extends DuplicateSchemaRuleException
{
private static final String UNIQUE_INDEX_PREFIX = "uniqueness indexes";
private static final String INDEX_PREFIX = "indexes";

private static final String DUPLICATE_INDEX_RULE_MESSAGE_TEMPLATE =
"Multiple %s found for label '%s' and property '%s'.";

public DuplicateIndexSchemaRuleException( int ruleEntityId, int propertyKeyId,
boolean unique )
{
super( DUPLICATE_INDEX_RULE_MESSAGE_TEMPLATE, ruleEntityId, propertyKeyId,
unique ? UNIQUE_INDEX_PREFIX : INDEX_PREFIX );
}

@Override
public String getUserMessage( TokenNameLookup tokenNameLookup )
{
return format( messageTemplate, messagePrefix,
tokenNameLookup.labelGetName( ruleEntityId ),
tokenNameLookup.propertyKeyGetName( propertyKeyId ) );
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2002-2015 "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.kernel.api.exceptions.schema;

import org.neo4j.kernel.api.exceptions.Status;

public abstract class DuplicateSchemaRuleException extends SchemaRuleException
{
protected static final String UNIQUE_CONSTRAINT_PREFIX = "uniqueness constraints";
protected static final String CONSTRAINT_PREFIX = "constraints";

protected DuplicateSchemaRuleException( String messageTemplate, int ruleEntityId, int propertyKeyId, String
messagePrefix )
{
super( Status.Schema.DuplicateSchemaRule, messageTemplate, ruleEntityId, propertyKeyId, messagePrefix );
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2002-2015 "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.kernel.api.exceptions.schema;

import org.neo4j.kernel.api.EntityType;
import org.neo4j.kernel.api.TokenNameLookup;

public class EntitySchemaRuleNotFoundException extends SchemaRuleNotFoundException
{
private static final String NODE_RULE_NOT_FOUND_MESSAGE_TEMPLATE =
"%s for label '%s' and property '%s' not found.";
private static final String RELATIONSHIP_RULE_NOT_FOUND_MESSAGE_TEMPLATE =
"%s for relationship type '%s' and property '%s' not found.";
private EntityType entityType;

public EntitySchemaRuleNotFoundException( EntityType entityType, int labelId, int propertyKeyId )
{
this( entityType, labelId, propertyKeyId, false );
}

public EntitySchemaRuleNotFoundException( EntityType entityType, int entityId, int propertyKeyId, boolean unique )
{
super( getMessageTemplate( entityType ), entityId, propertyKeyId,
unique ? UNIQUE_CONSTRAINT_PREFIX : CONSTRAINT_PREFIX );
this.entityType = entityType;
}

@Override
public String getUserMessage( TokenNameLookup tokenNameLookup )
{
String entityName = EntityType.NODE == entityType ? tokenNameLookup.labelGetName( ruleEntityId ) :
tokenNameLookup.relationshipTypeGetName( ruleEntityId );
return String.format( messageTemplate, messagePrefix, entityName,
tokenNameLookup.propertyKeyGetName( propertyKeyId ) );
}

private static String getMessageTemplate( EntityType entityType )
{
switch ( entityType )
{
case NODE:
return NODE_RULE_NOT_FOUND_MESSAGE_TEMPLATE;
case RELATIONSHIP:
return RELATIONSHIP_RULE_NOT_FOUND_MESSAGE_TEMPLATE;
default:
throw new IllegalArgumentException( "Schema rules for specified entityType not supported." );
}
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2002-2015 "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.kernel.api.exceptions.schema;

import org.neo4j.kernel.api.TokenNameLookup;

public class IndexSchemaRuleNotFoundException extends SchemaRuleNotFoundException
{
private static final String UNIQUE_INDEX_PREFIX = "Uniqueness index";
private static final String INDEX_PREFIX = "Index";
private static final String INDEX_RULE_NOT_FOUND_MESSAGE_TEMPLATE =
"%s for label '%s' and property '%s' not found.";

public IndexSchemaRuleNotFoundException( int labelId, int propertyKeyId )
{
this( labelId, propertyKeyId, false );
}

public IndexSchemaRuleNotFoundException( int labelId, int propertyKeyId, boolean unique )
{
super( INDEX_RULE_NOT_FOUND_MESSAGE_TEMPLATE, labelId, propertyKeyId,
unique ? UNIQUE_INDEX_PREFIX : INDEX_PREFIX );
}

@Override
public String getUserMessage( TokenNameLookup tokenNameLookup )
{
return String.format( messageTemplate, messagePrefix,
tokenNameLookup.labelGetName( ruleEntityId ),
tokenNameLookup.propertyKeyGetName( propertyKeyId ) );
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2002-2015 "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.kernel.api.exceptions.schema;

import org.neo4j.kernel.api.exceptions.Status;

import static java.lang.String.format;

public class SchemaRuleException extends SchemaKernelException
{

protected final int ruleEntityId;
protected final int propertyKeyId;
protected final String messageTemplate;
protected final String messagePrefix;

protected SchemaRuleException( Status status, String messageTemplate, int ruleEntityId, int propertyKeyId,
String messagePrefix)
{
super( status, format( messageTemplate, messagePrefix, ruleEntityId, propertyKeyId ) );
this.ruleEntityId = ruleEntityId;
this.propertyKeyId = propertyKeyId;
this.messageTemplate = messageTemplate;
this.messagePrefix = messagePrefix;
}
}

0 comments on commit 12c003f

Please sign in to comment.