From 717b6efdc65609090e28ec05415a6013cbbd1c80 Mon Sep 17 00:00:00 2001 From: zcourts Date: Sat, 30 Jun 2018 06:33:38 +0100 Subject: [PATCH 1/3] use an index name that is guaranteed to be no more than 255 chars --- .../ogm/datastore/ignite/impl/IgniteCacheInitializer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java index a31156e15..19908622e 100644 --- a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java +++ b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java @@ -12,6 +12,7 @@ import java.util.LinkedHashMap; import java.util.Optional; import java.util.Set; +import java.util.UUID; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.QueryEntity; @@ -180,7 +181,7 @@ private void appendIndex(QueryEntity queryEntity, AssociationKeyMetadata associa fields.put( realColumnName, true ); } queryIndex.setFields( fields ); - queryIndex.setName( queryEntity.getTableName() + '_' + org.hibernate.ogm.util.impl.StringHelper.join( fields.keySet(), "_" ) ); + queryIndex.setName( UUID.randomUUID().toString().replace( "-", "_" ) ); Set indexes = new HashSet<>( queryEntity.getIndexes() ); indexes.add( queryIndex ); From d85297f9fc34bd3c8cfefb37378eaf07dd3df447 Mon Sep 17 00:00:00 2001 From: zcourts Date: Fri, 10 Aug 2018 00:18:11 +0100 Subject: [PATCH 2/3] OGM-1507 Use custom @Index if available and fail if either custom or generated index name length > 255 --- .../ignite/impl/IgniteCacheInitializer.java | 16 ++++- .../datastore/ignite/logging/impl/Log.java | 3 + .../ignite/test/cfg/LongIndexNameTest.java | 55 ++++++++++++++++ .../LongIndexNameWithIndexAnnotationTest.java | 66 +++++++++++++++++++ 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java create mode 100644 ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java diff --git a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java index 19908622e..787184a44 100644 --- a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java +++ b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java @@ -181,7 +181,21 @@ private void appendIndex(QueryEntity queryEntity, AssociationKeyMetadata associa fields.put( realColumnName, true ); } queryIndex.setFields( fields ); - queryIndex.setName( UUID.randomUUID().toString().replace( "-", "_" ) ); + String indexName = queryEntity.getTableName() + '_' + org.hibernate.ogm.util.impl.StringHelper.join( fields.keySet(), "_" ); + Class tableClass = context.getTableEntityTypeMapping().get( associationKeyMetadata.getAssociatedEntityKeyMetadata().getEntityKeyMetadata().getTable() ); + javax.persistence.Table tableAnnotation = tableClass.getAnnotation( javax.persistence.Table.class ); + if( tableAnnotation != null && tableAnnotation.indexes().length > 0) { + for(javax.persistence.Index index: tableAnnotation.indexes()){ + if(!index.name().isEmpty()) { + indexName = index.name(); + break; + } + } + } + if ( indexName.getBytes().length > 255 ) { + throw log.indexNameTooLong(indexName, queryEntity.getTableName()); + } + queryIndex.setName( indexName ); Set indexes = new HashSet<>( queryEntity.getIndexes() ); indexes.add( queryIndex ); diff --git a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/logging/impl/Log.java b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/logging/impl/Log.java index 4894f74c4..89ba01b07 100644 --- a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/logging/impl/Log.java +++ b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/logging/impl/Log.java @@ -49,4 +49,7 @@ public interface Log extends org.hibernate.ogm.util.impl.Log { @Message(id = 1710, value = "Neither " + IgniteProperties.CONFIGURATION_RESOURCE_NAME + " nor " + IgniteProperties.CONFIGURATION_CLASS_NAME + " properties are set") HibernateException configurationNotSet(); + + @Message(id = 1711, value = "Invalid index name '%s' for entity '%s'. It must not be longer than 255 bytes. Use javax.persistence.@Index to override") + HibernateException indexNameTooLong(String indexName, String entityName); } diff --git a/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java new file mode 100644 index 000000000..6759afd00 --- /dev/null +++ b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java @@ -0,0 +1,55 @@ +/* + * Hibernate OGM, Domain model persistence for NoSQL datastores + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.ogm.datastore.ignite.test.cfg; + +import org.hibernate.HibernateException; +import org.hibernate.ogm.utils.OgmTestCase; +import org.junit.Test; +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; +import static org.junit.Assert.*; + +/** + * Entities with long names that results in an index with greater than 255 chars is invalid in Ignite. + * This ensures we raise an error and provide useful information to the user + */ +public class LongIndexNameTest extends OgmTestCase { + + @Test(expected = HibernateException.class) + public void testLongEntityIndexName() throws Exception { + fail("The length of the registered entity's cache name should've failed this already"); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + LongEntityName.class, + LongEntityContainer.class + }; + } + + @Entity + public static class LongEntityContainer { + @Id + private String id; + + @OneToMany(targetEntity = LongEntityName.class) + private Set longEntityNames = new HashSet<>(); + + @javax.persistence.JoinTable(name = "joinLongEntityName") + public Set getLongEntityNames() { + return longEntityNames; + } + } + + @Entity(name = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dapibus cursus vestibulum. Quisque eu justo non mi tincidunt sagittis. Donec tincidunt facilisis placerat. Sed placerat urna eget tristique faucibus. Curabitur maximus gravida enim, vitae sed") + public static class LongEntityName { + @Id + private String id; + } +} diff --git a/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java new file mode 100644 index 000000000..58561b3c9 --- /dev/null +++ b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java @@ -0,0 +1,66 @@ +/* + * Hibernate OGM, Domain model persistence for NoSQL datastores + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.ogm.datastore.ignite.test.cfg; + +import org.apache.ignite.cache.QueryIndex; +import org.hibernate.HibernateException; +import org.hibernate.ogm.OgmSession; +import org.hibernate.ogm.datastore.ignite.utils.IgniteTestHelper; +import org.hibernate.ogm.utils.OgmTestCase; +import org.junit.Test; + +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.fail; + +/** + * Entities with long names that results in an index with greater than 255 chars is invalid in Ignite. + * This ensures we raise an error and provide useful information to the user + */ +public class LongIndexNameWithIndexAnnotationTest extends OgmTestCase { + + @Test + public void testLongEntityIndexName() throws Exception { + try ( OgmSession session = openSession() ) { + Set indexes = IgniteTestHelper.getIndexes( session.getSessionFactory(), EntityWithCustomIndex.class ); + assertThat( indexes.size() ).isEqualTo( 1 ); + assertThat( indexes.iterator().next().getName() ).isEqualToIgnoringCase( "SimpleIndexName" ); + } + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + EntityWithCustomIndex.class, + EntityWithCustomContainer.class + }; + } + + @Entity + public static class EntityWithCustomContainer { + @Id + private String id; + + @OneToMany(targetEntity = EntityWithCustomIndex.class) + private Set entityWithCustomIndices = new HashSet<>(); + + @javax.persistence.JoinTable(name = "joinLongEntityName") + public Set getEntityWithCustomIndices() { + return entityWithCustomIndices; + } + } + + @Entity(name = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dapibus cursus vestibulum. Quisque eu justo non mi tincidunt sagittis. Donec tincidunt facilisis placerat. Sed placerat urna eget tristique faucibus. Curabitur maximus gravida enim, vitae sed") + @Table(indexes = {@Index(name = "SimpleIndexName", columnList = "id")}) + public static class EntityWithCustomIndex { + @Id + private String id; + } +} From b2e5d7154f6241213819c00c9267e5290744d9a3 Mon Sep 17 00:00:00 2001 From: zcourts Date: Sat, 11 Aug 2018 22:46:51 +0100 Subject: [PATCH 3/3] OGM-1507 Use hash of an entity's fields to reduce index name length --- .../datastore/ignite/impl/IgniteCacheInitializer.java | 10 +++++----- .../datastore/ignite/test/cfg/LongIndexNameTest.java | 10 +++++++--- .../test/cfg/LongIndexNameWithIndexAnnotationTest.java | 8 +++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java index 787184a44..060fe98b8 100644 --- a/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java +++ b/ignite/src/main/java/org/hibernate/ogm/datastore/ignite/impl/IgniteCacheInitializer.java @@ -181,19 +181,19 @@ private void appendIndex(QueryEntity queryEntity, AssociationKeyMetadata associa fields.put( realColumnName, true ); } queryIndex.setFields( fields ); - String indexName = queryEntity.getTableName() + '_' + org.hibernate.ogm.util.impl.StringHelper.join( fields.keySet(), "_" ); + String indexName = queryEntity.getTableName() + '_' + UUID.nameUUIDFromBytes( org.hibernate.ogm.util.impl.StringHelper.join( fields.keySet(), "_" ).getBytes() ); Class tableClass = context.getTableEntityTypeMapping().get( associationKeyMetadata.getAssociatedEntityKeyMetadata().getEntityKeyMetadata().getTable() ); javax.persistence.Table tableAnnotation = tableClass.getAnnotation( javax.persistence.Table.class ); - if( tableAnnotation != null && tableAnnotation.indexes().length > 0) { - for(javax.persistence.Index index: tableAnnotation.indexes()){ - if(!index.name().isEmpty()) { + if ( tableAnnotation != null && tableAnnotation.indexes().length > 0 ) { + for ( javax.persistence.Index index: tableAnnotation.indexes() ) { + if ( !index.name().isEmpty() ) { indexName = index.name(); break; } } } if ( indexName.getBytes().length > 255 ) { - throw log.indexNameTooLong(indexName, queryEntity.getTableName()); + throw log.indexNameTooLong( indexName, queryEntity.getTableName() ); } queryIndex.setName( indexName ); diff --git a/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java index 6759afd00..fbfd10132 100644 --- a/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java +++ b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameTest.java @@ -9,10 +9,14 @@ import org.hibernate.HibernateException; import org.hibernate.ogm.utils.OgmTestCase; import org.junit.Test; -import javax.persistence.*; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; import java.util.HashSet; import java.util.Set; -import static org.junit.Assert.*; + +import static junit.framework.TestCase.fail; /** * Entities with long names that results in an index with greater than 255 chars is invalid in Ignite. @@ -22,7 +26,7 @@ public class LongIndexNameTest extends OgmTestCase { @Test(expected = HibernateException.class) public void testLongEntityIndexName() throws Exception { - fail("The length of the registered entity's cache name should've failed this already"); + fail( "The length of the registered entity's cache name should've failed this already" ); } @Override diff --git a/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java index 58561b3c9..c110a07aa 100644 --- a/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java +++ b/ignite/src/test/java/org/hibernate/ogm/datastore/ignite/test/cfg/LongIndexNameWithIndexAnnotationTest.java @@ -7,18 +7,20 @@ package org.hibernate.ogm.datastore.ignite.test.cfg; import org.apache.ignite.cache.QueryIndex; -import org.hibernate.HibernateException; import org.hibernate.ogm.OgmSession; import org.hibernate.ogm.datastore.ignite.utils.IgniteTestHelper; import org.hibernate.ogm.utils.OgmTestCase; import org.junit.Test; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.OneToMany; +import javax.persistence.Table; import java.util.HashSet; import java.util.Set; import static org.fest.assertions.Assertions.assertThat; -import static org.junit.Assert.fail; /** * Entities with long names that results in an index with greater than 255 chars is invalid in Ignite.