Skip to content

Commit

Permalink
Test and fix supplied index provider
Browse files Browse the repository at this point in the history
  • Loading branch information
ragadeeshu committed May 21, 2018
1 parent 7680077 commit aa7ef22
Show file tree
Hide file tree
Showing 25 changed files with 370 additions and 79 deletions.
Expand Up @@ -32,12 +32,12 @@
import org.neo4j.internal.kernel.api.InternalIndexState; import org.neo4j.internal.kernel.api.InternalIndexState;
import org.neo4j.kernel.api.index.IndexAccessor; import org.neo4j.kernel.api.index.IndexAccessor;
import org.neo4j.kernel.api.index.IndexProvider; import org.neo4j.kernel.api.index.IndexProvider;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;
import org.neo4j.kernel.impl.api.index.IndexProviderMap; import org.neo4j.kernel.impl.api.index.IndexProviderMap;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig;
import org.neo4j.kernel.impl.store.RecordStore; import org.neo4j.kernel.impl.store.RecordStore;
import org.neo4j.kernel.impl.store.SchemaStorage; import org.neo4j.kernel.impl.store.SchemaStorage;
import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.DynamicRecord;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;


public class IndexAccessors implements Closeable public class IndexAccessors implements Closeable
{ {
Expand Down Expand Up @@ -98,7 +98,7 @@ public IndexAccessors( IndexProviderMap providers,


private IndexProvider provider( IndexProviderMap providers, StoreIndexDescriptor indexRule ) private IndexProvider provider( IndexProviderMap providers, StoreIndexDescriptor indexRule )
{ {
return providers.apply( indexRule.providerDescriptor() ); return providers.lookup( indexRule.providerDescriptor() );
} }


public Collection<StoreIndexDescriptor> notOnlineRules() public Collection<StoreIndexDescriptor> notOnlineRules()
Expand Down
Expand Up @@ -73,9 +73,7 @@
import org.neo4j.kernel.api.labelscan.LabelScanStore; import org.neo4j.kernel.api.labelscan.LabelScanStore;
import org.neo4j.kernel.api.labelscan.LabelScanWriter; import org.neo4j.kernel.api.labelscan.LabelScanWriter;
import org.neo4j.kernel.api.labelscan.NodeLabelUpdate; import org.neo4j.kernel.api.labelscan.NodeLabelUpdate;
import org.neo4j.kernel.api.schema.SchemaDescriptorFactory;
import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory; import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory;
import org.neo4j.kernel.api.schema.index.IndexDescriptorFactory;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor; import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;
import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.annotations.Documented; import org.neo4j.kernel.impl.annotations.Documented;
Expand Down Expand Up @@ -138,7 +136,6 @@
import static org.neo4j.kernel.api.schema.SchemaDescriptorFactory.forLabel; import static org.neo4j.kernel.api.schema.SchemaDescriptorFactory.forLabel;
import static org.neo4j.kernel.api.schema.index.IndexDescriptorFactory.forSchema; import static org.neo4j.kernel.api.schema.index.IndexDescriptorFactory.forSchema;
import static org.neo4j.kernel.api.schema.index.IndexDescriptorFactory.uniqueForSchema; import static org.neo4j.kernel.api.schema.index.IndexDescriptorFactory.uniqueForSchema;
import static org.neo4j.kernel.api.schema.index.TestIndexDescriptorFactory.uniqueForLabel;
import static org.neo4j.kernel.impl.store.AbstractDynamicStore.readFullByteArrayFromHeavyRecords; import static org.neo4j.kernel.impl.store.AbstractDynamicStore.readFullByteArrayFromHeavyRecords;
import static org.neo4j.kernel.impl.store.DynamicArrayStore.allocateFromNumbers; import static org.neo4j.kernel.impl.store.DynamicArrayStore.allocateFromNumbers;
import static org.neo4j.kernel.impl.store.DynamicArrayStore.getRightArray; import static org.neo4j.kernel.impl.store.DynamicArrayStore.getRightArray;
Expand Down Expand Up @@ -456,7 +453,7 @@ public void shouldNotReportIndexInconsistenciesIfIndexIsFailed() throws Exceptio
{ {
StoreIndexDescriptor rule = rules.next(); StoreIndexDescriptor rule = rules.next();
IndexSamplingConfig samplingConfig = new IndexSamplingConfig( Config.defaults() ); IndexSamplingConfig samplingConfig = new IndexSamplingConfig( Config.defaults() );
IndexPopulator populator = storeAccess.indexes().apply( rule.providerDescriptor() ) IndexPopulator populator = storeAccess.indexes().lookup( rule.providerDescriptor() )
.getPopulator( rule, samplingConfig ); .getPopulator( rule, samplingConfig );
populator.markAsFailed( "Oh noes! I was a shiny index and then I was failed" ); populator.markAsFailed( "Oh noes! I was a shiny index and then I was failed" );
populator.close( false ); populator.close( false );
Expand Down Expand Up @@ -566,7 +563,7 @@ public void shouldReportNodesThatAreNotIndexed() throws Exception
{ {
StoreIndexDescriptor indexDescriptor = indexDescriptorIterator.next(); StoreIndexDescriptor indexDescriptor = indexDescriptorIterator.next();
IndexAccessor accessor = fixture.directStoreAccess().indexes(). IndexAccessor accessor = fixture.directStoreAccess().indexes().
apply( indexDescriptor.providerDescriptor() ).getOnlineAccessor( indexDescriptor, samplingConfig ); lookup( indexDescriptor.providerDescriptor() ).getOnlineAccessor( indexDescriptor, samplingConfig );
try ( IndexUpdater updater = accessor.newUpdater( IndexUpdateMode.ONLINE ) ) try ( IndexUpdater updater = accessor.newUpdater( IndexUpdateMode.ONLINE ) )
{ {
for ( long nodeId : indexedNodes ) for ( long nodeId : indexedNodes )
Expand Down Expand Up @@ -600,7 +597,7 @@ public void shouldReportNodesWithDuplicatePropertyValueInUniqueIndex() throws Ex
while ( indexRuleIterator.hasNext() ) while ( indexRuleIterator.hasNext() )
{ {
StoreIndexDescriptor indexRule = indexRuleIterator.next(); StoreIndexDescriptor indexRule = indexRuleIterator.next();
IndexAccessor accessor = fixture.directStoreAccess().indexes().apply( indexRule.providerDescriptor() ) IndexAccessor accessor = fixture.directStoreAccess().indexes().lookup( indexRule.providerDescriptor() )
.getOnlineAccessor( indexRule, samplingConfig ); .getOnlineAccessor( indexRule, samplingConfig );
IndexUpdater updater = accessor.newUpdater( IndexUpdateMode.ONLINE ); IndexUpdater updater = accessor.newUpdater( IndexUpdateMode.ONLINE );
updater.process( IndexEntryUpdate.add( 42, indexRule.schema(), values( indexRule ) ) ); updater.process( IndexEntryUpdate.add( 42, indexRule.schema(), values( indexRule ) ) );
Expand Down
Expand Up @@ -40,6 +40,14 @@ public interface SchemaWrite
*/ */
IndexReference indexCreate( SchemaDescriptor descriptor ) throws SchemaKernelException; IndexReference indexCreate( SchemaDescriptor descriptor ) throws SchemaKernelException;


/**
* Create index from schema descriptor
*
* @param descriptor description of the index
* @param provider name of the desired index provider implementation
* @param name name of the index
* @return the newly created index
*/
IndexReference indexCreate( SchemaDescriptor descriptor, IndexReference indexCreate( SchemaDescriptor descriptor,
Optional<String> provider, Optional<String> provider,
Optional<String> name ) throws SchemaKernelException; Optional<String> name ) throws SchemaKernelException;
Expand All @@ -58,13 +66,31 @@ IndexReference indexCreate( SchemaDescriptor descriptor,
*/ */
ConstraintDescriptor uniquePropertyConstraintCreate( SchemaDescriptor descriptor ) throws SchemaKernelException; ConstraintDescriptor uniquePropertyConstraintCreate( SchemaDescriptor descriptor ) throws SchemaKernelException;


/**
* Create unique property constraint
*
* @param descriptor description of the constraint
* @param provider name of the desired index provider implementation
*/
ConstraintDescriptor uniquePropertyConstraintCreate( SchemaDescriptor descriptor,
Optional<String> provider ) throws SchemaKernelException;

/** /**
* Create node key constraint * Create node key constraint
* *
* @param descriptor description of the constraint * @param descriptor description of the constraint
*/ */
ConstraintDescriptor nodeKeyConstraintCreate( LabelSchemaDescriptor descriptor ) throws SchemaKernelException; ConstraintDescriptor nodeKeyConstraintCreate( LabelSchemaDescriptor descriptor ) throws SchemaKernelException;


/**
* Create node key constraint
*
* @param descriptor description of the constraint
* @param provider name of the desired index provider implementation
*/
ConstraintDescriptor nodeKeyConstraintCreate( LabelSchemaDescriptor descriptor,
Optional<String> provider ) throws SchemaKernelException;

/** /**
* Create node property existence constraint * Create node property existence constraint
* *
Expand Down
Expand Up @@ -19,6 +19,8 @@
*/ */
package org.neo4j.kernel.api; package org.neo4j.kernel.api;


import java.util.Optional;

import org.neo4j.graphdb.NotInTransactionException; import org.neo4j.graphdb.NotInTransactionException;
import org.neo4j.internal.kernel.api.NodeCursor; import org.neo4j.internal.kernel.api.NodeCursor;
import org.neo4j.internal.kernel.api.PropertyCursor; import org.neo4j.internal.kernel.api.PropertyCursor;
Expand Down Expand Up @@ -59,9 +61,10 @@ interface CloseListener
* Create unique index which will be used to support uniqueness constraint. * Create unique index which will be used to support uniqueness constraint.
* *
* @param schema schema to create unique index for. * @param schema schema to create unique index for.
* @param provider
* @return IndexDescriptor for the index to be created. * @return IndexDescriptor for the index to be created.
*/ */
IndexDescriptor indexUniqueCreate( SchemaDescriptor schema ); IndexDescriptor indexUniqueCreate( SchemaDescriptor schema, Optional<String> provider );


/** /**
* @return the security context this transaction is currently executing in. * @return the security context this transaction is currently executing in.
Expand Down
Expand Up @@ -26,8 +26,8 @@
import org.neo4j.internal.kernel.api.InternalIndexState; import org.neo4j.internal.kernel.api.InternalIndexState;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache; import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;
import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.api.schema.index.IndexDescriptor;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;
import org.neo4j.kernel.impl.api.index.IndexingService; import org.neo4j.kernel.impl.api.index.IndexingService;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig;
import org.neo4j.kernel.impl.storemigration.StoreMigrationParticipant; import org.neo4j.kernel.impl.storemigration.StoreMigrationParticipant;
Expand Down Expand Up @@ -303,6 +303,14 @@ public String getVersion()
return version; return version;
} }


/**
* @return a combination of {@link #getKey()} and {@link #getVersion()} with a '-' in between.
*/
public String name()
{
return key + "-" + version;
}

@Override @Override
public int hashCode() public int hashCode()
{ {
Expand Down
Expand Up @@ -21,7 +21,6 @@


import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Label;
import org.neo4j.internal.kernel.api.IndexCapability; import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.kernel.api.index.IndexProvider;
import org.neo4j.kernel.impl.api.index.IndexProviderMap; import org.neo4j.kernel.impl.api.index.IndexProviderMap;
import org.neo4j.storageengine.api.schema.SchemaRule; import org.neo4j.storageengine.api.schema.SchemaRule;


Expand Down Expand Up @@ -137,7 +136,7 @@ public CapableIndexDescriptor withoutCapabilities()


public CapableIndexDescriptor withCapabilities( IndexProviderMap indexProviderMap ) public CapableIndexDescriptor withCapabilities( IndexProviderMap indexProviderMap )
{ {
IndexCapability capability = indexProviderMap.apply( providerDescriptor ).getCapability(); IndexCapability capability = indexProviderMap.lookup( providerDescriptor ).getCapability();
return new CapableIndexDescriptor( this, capability ); return new CapableIndexDescriptor( this, capability );
} }
} }
Expand Up @@ -396,9 +396,9 @@ public KernelStatement acquireStatement()
} }


@Override @Override
public IndexDescriptor indexUniqueCreate( SchemaDescriptor schema ) public IndexDescriptor indexUniqueCreate( SchemaDescriptor schema, Optional<String> provider )
{ {
return operations.indexUniqueCreate( schema ); return operations.indexUniqueCreate( schema, provider );
} }


@Override @Override
Expand Down
Expand Up @@ -20,23 +20,57 @@
package org.neo4j.kernel.impl.api.index; package org.neo4j.kernel.impl.api.index;


import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;


import org.neo4j.kernel.api.index.IndexProvider; import org.neo4j.kernel.api.index.IndexProvider;


public interface IndexProviderMap extends Function<IndexProvider.Descriptor,IndexProvider> /**
* Contains mapping from {@link IndexProvider.Descriptor} or provider name to {@link IndexProvider}.
*/
public interface IndexProviderMap
{ {
@Override /**
IndexProvider apply( IndexProvider.Descriptor descriptor ) throws IndexProviderNotFoundException; * Looks up and returns the {@link IndexProvider} for the given {@link IndexProvider.Descriptor}.
*
* @param providerDescriptor the descriptor identifying the {@link IndexProvider}.
* @return the {@link IndexProvider} with the given {@link IndexProvider.Descriptor}.
* @throws IndexProviderNotFoundException if no such {@link IndexProvider} was found.
*/
IndexProvider lookup( IndexProvider.Descriptor providerDescriptor ) throws IndexProviderNotFoundException;

/**
* Looks up and returns the {@link IndexProvider} for the given index provider name. The name is what
* an {@link IndexProvider.Descriptor#name()} call would return.
*
* @param providerDescriptorName the descriptor name identifying the {@link IndexProvider}.
* @return the {@link IndexProvider} with the given name.
* @throws IndexProviderNotFoundException if no such {@link IndexProvider} was found.
*/
IndexProvider lookup( String providerDescriptorName ) throws IndexProviderNotFoundException;


/**
* There's always a default {@link IndexProvider}, this method returns it.
*
* @return the default index provider for this instance.
*/
IndexProvider getDefaultProvider(); IndexProvider getDefaultProvider();


/**
* Visits all the {@link IndexProvider} with the visitor.
*
* @param visitor {@link Consumer} visiting all the {@link IndexProvider index providers} in this map.
*/
void accept( Consumer<IndexProvider> visitor ); void accept( Consumer<IndexProvider> visitor );


IndexProviderMap EMPTY = new IndexProviderMap() IndexProviderMap EMPTY = new IndexProviderMap()
{ {
@Override @Override
public IndexProvider apply( IndexProvider.Descriptor descriptor ) throws IndexProviderNotFoundException public IndexProvider lookup( IndexProvider.Descriptor descriptor ) throws IndexProviderNotFoundException
{
return IndexProvider.EMPTY;
}

@Override
public IndexProvider lookup( String providerDescriptorName ) throws IndexProviderNotFoundException
{ {
return IndexProvider.EMPTY; return IndexProvider.EMPTY;
} }
Expand Down
Expand Up @@ -145,13 +145,13 @@ private String indexUserDescription( final StoreIndexDescriptor descriptor )


private IndexPopulator populatorFromProvider( StoreIndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) private IndexPopulator populatorFromProvider( StoreIndexDescriptor descriptor, IndexSamplingConfig samplingConfig )
{ {
IndexProvider indexProvider = providerMap.apply( descriptor.providerDescriptor() ); IndexProvider indexProvider = providerMap.lookup( descriptor.providerDescriptor() );
return indexProvider.getPopulator( descriptor, samplingConfig ); return indexProvider.getPopulator( descriptor, samplingConfig );
} }


private IndexAccessor onlineAccessorFromProvider( StoreIndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException private IndexAccessor onlineAccessorFromProvider( StoreIndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException
{ {
IndexProvider indexProvider = providerMap.apply( descriptor.providerDescriptor() ); IndexProvider indexProvider = providerMap.lookup( descriptor.providerDescriptor() );
return indexProvider.getOnlineAccessor( descriptor, samplingConfig ); return indexProvider.getOnlineAccessor( descriptor, samplingConfig );
} }


Expand Down
Expand Up @@ -54,11 +54,11 @@
import org.neo4j.kernel.api.index.IndexProvider; import org.neo4j.kernel.api.index.IndexProvider;
import org.neo4j.kernel.api.index.IndexUpdater; import org.neo4j.kernel.api.index.IndexUpdater;
import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.api.schema.index.IndexDescriptor;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;
import org.neo4j.kernel.impl.api.SchemaState; import org.neo4j.kernel.impl.api.SchemaState;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingController; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingController;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingMode; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingMode;
import org.neo4j.kernel.impl.store.UnderlyingStorageException; import org.neo4j.kernel.impl.store.UnderlyingStorageException;
import org.neo4j.kernel.api.schema.index.StoreIndexDescriptor;
import org.neo4j.kernel.impl.transaction.state.IndexUpdates; import org.neo4j.kernel.impl.transaction.state.IndexUpdates;
import org.neo4j.kernel.lifecycle.LifecycleAdapter; import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.logging.Log; import org.neo4j.logging.Log;
Expand Down Expand Up @@ -202,7 +202,7 @@ public void init()
IndexProxy indexProxy; IndexProxy indexProxy;


IndexProvider.Descriptor providerDescriptor = indexDescriptor.providerDescriptor(); IndexProvider.Descriptor providerDescriptor = indexDescriptor.providerDescriptor();
IndexProvider provider = providerMap.apply( providerDescriptor ); IndexProvider provider = providerMap.lookup( providerDescriptor );
InternalIndexState initialState = provider.getInitialState( indexDescriptor ); InternalIndexState initialState = provider.getInitialState( indexDescriptor );
indexStates.computeIfAbsent( initialState, internalIndexState -> new ArrayList<>() ) indexStates.computeIfAbsent( initialState, internalIndexState -> new ArrayList<>() )
.add( new IndexLogRecord( indexDescriptor ) ); .add( new IndexLogRecord( indexDescriptor ) );
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.neo4j.kernel.impl.api.state; package org.neo4j.kernel.impl.api.state;


import java.io.IOException; import java.io.IOException;
import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;


import org.neo4j.internal.kernel.api.IndexReference; import org.neo4j.internal.kernel.api.IndexReference;
Expand Down Expand Up @@ -89,8 +90,8 @@ public ConstraintIndexCreator( Supplier<Kernel> kernelSupplier, IndexingService
* and this tx committed, which will create the uniqueness constraint</li> * and this tx committed, which will create the uniqueness constraint</li>
* </ol> * </ol>
*/ */
public long createUniquenessConstraintIndex( KernelTransactionImplementation transaction, public long createUniquenessConstraintIndex( KernelTransactionImplementation transaction, SchemaDescriptor descriptor, Optional<String> provider )
SchemaDescriptor descriptor ) throws TransactionFailureException, CreateConstraintFailureException, throws TransactionFailureException, CreateConstraintFailureException,
UniquePropertyValueValidationException, AlreadyConstrainedException UniquePropertyValueValidationException, AlreadyConstrainedException
{ {
UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor ); UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor );
Expand All @@ -99,7 +100,7 @@ public long createUniquenessConstraintIndex( KernelTransactionImplementation tra
SchemaRead schemaRead = transaction.schemaRead(); SchemaRead schemaRead = transaction.schemaRead();
try try
{ {
index = getOrCreateUniquenessConstraintIndex( schemaRead, transaction.tokenRead(), descriptor ); index = getOrCreateUniquenessConstraintIndex( schemaRead, transaction.tokenRead(), descriptor, provider );
} }
catch ( AlreadyConstrainedException e ) catch ( AlreadyConstrainedException e )
{ {
Expand Down Expand Up @@ -226,8 +227,8 @@ private void awaitConstrainIndexPopulation( UniquenessConstraintDescriptor const
} }
} }


private IndexReference getOrCreateUniquenessConstraintIndex( SchemaRead schemaRead, private IndexReference getOrCreateUniquenessConstraintIndex( SchemaRead schemaRead, TokenRead tokenRead, SchemaDescriptor schema,
TokenRead tokenRead, SchemaDescriptor schema ) Optional<String> provider )
throws SchemaKernelException, IndexNotFoundKernelException throws SchemaKernelException, IndexNotFoundKernelException
{ {
IndexReference descriptor = schemaRead.index( schema.keyId(), schema.getPropertyIds() ); IndexReference descriptor = schemaRead.index( schema.keyId(), schema.getPropertyIds() );
Expand All @@ -250,19 +251,19 @@ private IndexReference getOrCreateUniquenessConstraintIndex( SchemaRead schemaRe
// There's already an index for this schema descriptor, which isn't of the type we're after. // There's already an index for this schema descriptor, which isn't of the type we're after.
throw new AlreadyIndexedException( schema, CONSTRAINT_CREATION ); throw new AlreadyIndexedException( schema, CONSTRAINT_CREATION );
} }
IndexDescriptor indexDescriptor = createConstraintIndex( schema ); IndexDescriptor indexDescriptor = createConstraintIndex( schema, provider );
IndexProxy indexProxy = indexingService.getIndexProxy( indexDescriptor.schema() ); IndexProxy indexProxy = indexingService.getIndexProxy( indexDescriptor.schema() );
return indexProxy.getDescriptor(); return indexProxy.getDescriptor();
} }


public IndexDescriptor createConstraintIndex( final SchemaDescriptor schema ) public IndexDescriptor createConstraintIndex( final SchemaDescriptor schema, Optional<String> provider )
{ {
try ( Session session = kernelSupplier.get().beginSession( AUTH_DISABLED ); try ( Session session = kernelSupplier.get().beginSession( AUTH_DISABLED );
Transaction transaction = session.beginTransaction( Transaction.Type.implicit ); Transaction transaction = session.beginTransaction( Transaction.Type.implicit );
//TODO remove statement? //TODO remove statement?
Statement ignore = ((KernelTransaction)transaction).acquireStatement() ) Statement ignore = ((KernelTransaction)transaction).acquireStatement() )
{ {
IndexDescriptor index = ((KernelTransaction)transaction).indexUniqueCreate( schema ); IndexDescriptor index = ((KernelTransaction) transaction).indexUniqueCreate( schema, provider );
transaction.success(); transaction.success();
return index; return index;
} }
Expand Down

0 comments on commit aa7ef22

Please sign in to comment.