use of org.neo4j.internal.schema.IndexDescriptor in project neo4j by neo4j.
the class IndexConfigMigrationIT method getIndexConfig.
@SuppressWarnings("SameParameterValue")
private static Map<String, Value> getIndexConfig(GraphDatabaseAPI db, Transaction tx, Label label) throws IndexNotFoundKernelException {
IndexDefinitionImpl indexDefinition = (IndexDefinitionImpl) single(tx.schema().getIndexes(label));
IndexDescriptor index = indexDefinition.getIndexReference();
IndexingService indexingService = getIndexingService(db);
IndexProxy indexProxy = indexingService.getIndexProxy(index);
return indexProxy.indexConfig();
}
use of org.neo4j.internal.schema.IndexDescriptor in project neo4j by neo4j.
the class NonUniqueIndexTest method concurrentIndexPopulationAndInsertsShouldNotProduceDuplicates.
@Test
void concurrentIndexPopulationAndInsertsShouldNotProduceDuplicates() throws Exception {
// Given
GraphDatabaseService db = newEmbeddedGraphDatabaseWithSlowJobScheduler();
try {
// When
try (Transaction tx = db.beginTx()) {
tx.schema().indexFor(label(LABEL)).on(KEY).withName(INDEX_NAME).create();
tx.commit();
}
Node node;
try (Transaction tx = db.beginTx()) {
node = tx.createNode(label(LABEL));
node.setProperty(KEY, VALUE);
tx.commit();
}
try (Transaction tx = db.beginTx()) {
tx.schema().awaitIndexesOnline(2, MINUTES);
tx.commit();
}
// Then
try (Transaction tx = db.beginTx()) {
KernelTransaction ktx = ((InternalTransaction) tx).kernelTransaction();
IndexDescriptor index = ktx.schemaRead().indexGetForName(INDEX_NAME);
IndexReadSession indexSession = ktx.dataRead().indexReadSession(index);
try (NodeValueIndexCursor cursor = ktx.cursors().allocateNodeValueIndexCursor(ktx.cursorContext(), ktx.memoryTracker())) {
ktx.dataRead().nodeIndexSeek(indexSession, cursor, unconstrained(), PropertyIndexQuery.exact(1, VALUE));
assertTrue(cursor.next());
assertEquals(node.getId(), cursor.nodeReference());
assertFalse(cursor.next());
}
tx.commit();
}
} finally {
managementService.shutdown();
}
}
use of org.neo4j.internal.schema.IndexDescriptor in project neo4j by neo4j.
the class AbstractIndexQueryingTest method relationshipIndexSeekMustThrowOnWrongIndexEntityType.
@Test
void relationshipIndexSeekMustThrowOnWrongIndexEntityType() throws IndexNotFoundKernelException {
IndexDescriptor index = schemaRead.indexGetForName("ftsNodes");
IndexReadSession indexReadSession = read.indexReadSession(index);
try (RelationshipValueIndexCursor cursor = cursors.allocateRelationshipValueIndexCursor(NULL, EmptyMemoryTracker.INSTANCE)) {
assertThrows(IndexNotApplicableKernelException.class, () -> read.relationshipIndexSeek(indexReadSession, cursor, unconstrained(), PropertyIndexQuery.fulltextSearch("search")));
}
}
use of org.neo4j.internal.schema.IndexDescriptor in project neo4j by neo4j.
the class SchemaComplianceChecker method checkCorrectlyIndexed.
<ENTITY extends PrimitiveRecord> void checkCorrectlyIndexed(ENTITY entity, long[] entityTokens, IntObjectMap<Value> values, Function<ENTITY, ConsistencyReport.PrimitiveConsistencyReport> reportSupplier) {
for (IndexDescriptor indexRule : indexes) {
SchemaDescriptor schema = indexRule.schema();
Value[] valueArray = RecordLoading.entityIntersectionWithSchema(entityTokens, values, schema);
if (valueArray == null) {
continue;
}
var reader = indexReaders.reader(indexRule);
if (indexRule.isUnique()) {
verifyIndexedUniquely(entity, valueArray, indexRule, reader, reportSupplier);
} else {
long count = reader.countIndexedEntities(entity.getId(), cursorContext, schema.getPropertyIds(), valueArray);
reportIncorrectIndexCount(entity, valueArray, indexRule, count, reportSupplier);
}
}
}
use of org.neo4j.internal.schema.IndexDescriptor in project neo4j by neo4j.
the class IndexChecker method checkVsEntities.
private void checkVsEntities(List<IndexContext> indexes, long fromEntityId, long toEntityId) {
// This is one thread
CheckerContext noReportingContext = context.withoutReporting();
try (var cursorContext = new CursorContext(context.pageCacheTracer.createPageCursorTracer(CONSISTENCY_INDEX_ENTITY_CHECK_TAG));
RecordReader<NodeRecord> nodeReader = new RecordReader<>(context.neoStores.getNodeStore(), true, cursorContext);
RecordReader<DynamicRecord> labelReader = new RecordReader<>(context.neoStores.getNodeStore().getDynamicLabelStore(), false, cursorContext);
SafePropertyChainReader propertyReader = new SafePropertyChainReader(noReportingContext, cursorContext)) {
ProgressListener localScanProgress = scanProgress.threadLocalReporter();
IntObjectHashMap<Value> allValues = new IntObjectHashMap<>();
var client = cacheAccess.client();
int numberOfIndexes = indexes.size();
for (long entityId = fromEntityId; entityId < toEntityId && !context.isCancelled(); entityId++) {
NodeRecord nodeRecord = nodeReader.read(entityId);
if (nodeRecord.inUse()) {
long[] entityTokens = safeGetNodeLabels(noReportingContext, nodeRecord.getId(), nodeRecord.getLabelField(), labelReader, cursorContext);
lightClear(allValues);
boolean propertyChainRead = entityTokens != null && propertyReader.read(allValues, nodeRecord, noReportingContext.reporter::forNode, cursorContext);
if (propertyChainRead) {
for (int i = 0; i < numberOfIndexes; i++) {
IndexContext index = indexes.get(i);
IndexDescriptor descriptor = index.descriptor;
long cachedValue = client.getFromCache(entityId, i);
boolean nodeIsInIndex = (cachedValue & IN_USE_MASK) != 0;
Value[] values = RecordLoading.entityIntersectionWithSchema(entityTokens, allValues, descriptor.schema());
if (index.descriptor.schema().isFulltextSchemaDescriptor()) {
// The strategy for fulltext indexes is way simpler. Simply check of the sets of tokens (label tokens and property key tokens)
// and if they match the index schema descriptor then the node should be in the index, otherwise not
int[] nodePropertyKeys = allValues.keySet().toArray();
int[] indexPropertyKeys = index.descriptor.schema().getPropertyIds();
boolean nodeShouldBeInIndex = index.descriptor.schema().isAffected(entityTokens) && containsAny(indexPropertyKeys, nodePropertyKeys) && valuesContainTextProperty(values);
if (nodeShouldBeInIndex && !nodeIsInIndex) {
getReporter(context.recordLoader.node(entityId, cursorContext)).notIndexed(descriptor, new Object[0]);
} else if (!nodeShouldBeInIndex && nodeIsInIndex) {
// Fulltext indexes created before 4.3.0-drop02 can contain empty documents (added when the schema matched but the values
// were not text). The index still works with those empty documents present, so we don't want to report them as
// inconsistencies and force rebuilds.
// This utilizes the fact that countIndexedEntities in FulltextIndexReader with non-text values will ask
// about documents that doesn't contain those property keys - a document found by that query should be an empty
// document we just want to ignore.
Value[] noValues = new Value[indexPropertyKeys.length];
Arrays.fill(noValues, NO_VALUE);
long docsWithNoneOfProperties = indexAccessors.readers().reader(descriptor).countIndexedEntities(entityId, cursorContext, indexPropertyKeys, noValues);
if (docsWithNoneOfProperties != 1) {
getReporter(context.recordLoader.node(entityId, cursorContext)).notIndexed(descriptor, new Object[0]);
}
}
} else {
if (values != null) {
// This node should really be in the index, is it?
if (!nodeIsInIndex) {
// It wasn't, report it
getReporter(context.recordLoader.node(entityId, cursorContext)).notIndexed(descriptor, Values.asObjects(values));
} else if (index.hasValues) {
int cachedChecksum = (int) cachedValue & CHECKSUM_MASK;
int actualChecksum = checksum(values);
if (cachedChecksum != actualChecksum) {
getReporter(context.recordLoader.node(entityId, cursorContext)).notIndexed(descriptor, Values.asObjects(values));
}
}
} else {
if (nodeIsInIndex) {
reporter.forIndexEntry(new IndexEntry(descriptor, context.tokenNameLookup, entityId)).nodeNotInUse(context.recordLoader.node(entityId, cursorContext));
}
}
}
}
}
// else this would be reported elsewhere
} else {
// This node shouldn't be in any index
for (int i = 0; i < numberOfIndexes; i++) {
boolean isInIndex = (client.getFromCache(entityId, i) & IN_USE_MASK) != 0;
if (isInIndex) {
reporter.forIndexEntry(new IndexEntry(indexes.get(i).descriptor, context.tokenNameLookup, entityId)).nodeNotInUse(context.recordLoader.node(entityId, cursorContext));
}
}
}
localScanProgress.add(1);
}
localScanProgress.done();
}
}
Aggregations