Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graph store record id operations #240

Merged
merged 2 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class OStoreTransactionImpl(
requireActiveTransaction()
try {
return session.load(id.asOId())
} catch (e: RecordNotFoundException) {
} catch (_: RecordNotFoundException) {
throw EntityRemovedInDatabaseException(id.getTypeName(), id)
}

Expand Down Expand Up @@ -259,7 +259,7 @@ class OStoreTransactionImpl(
try {
val vertex: Vertex = session.load(oId.asOId())
return OVertexEntity(vertex, store)
} catch (e: RecordNotFoundException) {
} catch (_: RecordNotFoundException) {
throw EntityRemovedInDatabaseException(oId.getTypeName(), id)
}
}
Expand All @@ -276,7 +276,7 @@ class OStoreTransactionImpl(

override fun getSingletonIterable(entity: Entity): EntityIterable {
requireActiveTransaction()
return OSingleEntityIterable(this, entity)
return OMultipleEntitiesIterable(this, listOf(entity))
}

override fun find(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import jetbrains.exodus.entitystore.orientdb.iterate.binop.OMinusEntityIterable
import jetbrains.exodus.entitystore.orientdb.iterate.binop.OUnionEntityIterable
import jetbrains.exodus.entitystore.orientdb.iterate.link.OLinkIterableToEntityIterableFiltered
import jetbrains.exodus.entitystore.orientdb.iterate.link.OLinkSelectEntityIterable
import jetbrains.exodus.entitystore.orientdb.iterate.link.OSingleEntityIterable
import jetbrains.exodus.entitystore.orientdb.iterate.link.OMultipleEntitiesIterable
import jetbrains.exodus.entitystore.orientdb.query.*
import jetbrains.exodus.entitystore.util.unsupported

Expand Down Expand Up @@ -224,7 +224,7 @@ abstract class OEntityIterableBase(tx: OStoreTransaction) : OEntityIterable {

override fun contains(entity: Entity): Boolean {
val currentTx = oStore.requireActiveTransaction()
return OIntersectionEntityIterable(currentTx, this, OSingleEntityIterable(currentTx, entity)).iterator().hasNext()
return OIntersectionEntityIterable(currentTx, this, OMultipleEntitiesIterable(currentTx, listOf(entity))).iterator().hasNext()
}

override fun unwrap() = this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,61 @@ class OMultipleEntitiesIterable(tx: OStoreTransaction, val entities: List<Entity
}

override fun skip(number: Int): EntityIterable {
return OMultipleEntitiesIterable(transaction as OStoreTransaction, entities.drop(number) )
return if (number > entities.size){
EMPTY
} else {
OMultipleEntitiesIterable(transaction as OStoreTransaction, entities.drop(number))
}
}

override fun take(number: Int): EntityIterable {
return OMultipleEntitiesIterable(transaction as OStoreTransaction, entities.take(number) )
}

override fun union(right: EntityIterable): EntityIterable {
return if (right is OMultipleEntitiesIterable) {
OMultipleEntitiesIterable(transaction as OStoreTransaction, entities.union(right.entities).toList())
} else super.union(right)
}

override fun intersect(right: EntityIterable): EntityIterable {
return if (right is OMultipleEntitiesIterable) {
val otherEntitiesAsSet = right.entities.toSet()
val intersect = entities.filter { otherEntitiesAsSet.contains(it) }
if (intersect.isEmpty()){
EMPTY
} else {
OMultipleEntitiesIterable(transaction as OStoreTransaction, intersect)
}
} else super.intersect(right)
}

override fun intersectSavingOrder(right: EntityIterable): EntityIterable {
return if (right is OMultipleEntitiesIterable) {
val otherEntitiesAsSet = right.entities.toSet()
val intersect = entities.filter { otherEntitiesAsSet.contains(it) }
if (intersect.isEmpty()){
EMPTY
} else {
OMultipleEntitiesIterable(transaction as OStoreTransaction, intersect)
}
} else super.intersectSavingOrder(right)
}

override fun concat(right: EntityIterable): EntityIterable {
return if (right is OMultipleEntitiesIterable) {
OMultipleEntitiesIterable(transaction as OStoreTransaction, entities + right.entities)
} else super.concat(right)
}

override fun minus(right: EntityIterable): EntityIterable {
return if (right is OMultipleEntitiesIterable) {
val minus = entities.toSet().minus(right.entities)
if (minus.isEmpty()){
EMPTY
} else {
OMultipleEntitiesIterable(transaction as OStoreTransaction, entities + right.entities)
}
} else super.minus(right)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ object OQueryFunctions {

fun difference(left: OSelect, right: OSelect): OSelect {
return when {
left is ORecordIdSelect && right is ORecordIdSelect -> {
ensureLimitIsNotUsed(left, right)
ensureSkipIsNotUsed(left, right)

val newOrder = left.order.merge(right.order)
val ids = left.recordIds - right.recordIds.toSet()
ORecordIdSelect(ids, newOrder)
}

left is OClassSelect && right is OClassSelect && isSameClassName(left, right) -> {
ensureInvariants(left, right)
Expand Down
3 changes: 2 additions & 1 deletion query/src/main/kotlin/jetbrains/exodus/query/SortEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import jetbrains.exodus.entitystore.EntityIterable
import jetbrains.exodus.entitystore.orientdb.OEntityIterable
import jetbrains.exodus.entitystore.orientdb.OVertexEntity
import jetbrains.exodus.entitystore.orientdb.iterate.OEntityIterableBase
import jetbrains.exodus.entitystore.orientdb.iterate.link.OMultipleEntitiesIterable
import jetbrains.exodus.query.metadata.ModelMetaData

open class SortEngine {
Expand Down Expand Up @@ -68,7 +69,7 @@ open class SortEngine {
source: Iterable<Entity>,
asc: Boolean
): Iterable<Entity> {
if (source is OEntityIterable) {
if (source is OEntityIterable && source !is OMultipleEntitiesIterable) {
val txn = queryEngine.persistentStore.andCheckCurrentTransaction
return txn.sort(entityType, "${OVertexEntity.edgeClassName(linkName)}.$propName", source.unwrap(), asc)
} else {
Expand Down
40 changes: 39 additions & 1 deletion query/src/test/kotlin/jetbrains/exodus/query/OQueryEngineTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import jetbrains.exodus.entitystore.Entity
import jetbrains.exodus.entitystore.EntityIterable
import jetbrains.exodus.entitystore.orientdb.OStoreTransaction
import jetbrains.exodus.entitystore.orientdb.iterate.OEntityIterableBase
import jetbrains.exodus.entitystore.orientdb.iterate.link.OMultipleEntitiesIterable
import jetbrains.exodus.entitystore.orientdb.testutil.*
import jetbrains.exodus.query.metadata.EntityMetaData
import jetbrains.exodus.query.metadata.ModelMetaData
Expand Down Expand Up @@ -53,7 +54,13 @@ class OQueryEngineTest(
it.id.typeId >= 0
}
InMemoryEntityIterable(filteringSequence.asIterable(), currentTx, engine)
}, "InMemory")
}, "InMemory"),
arrayOf({ engine: QueryEngine, currentTx: OStoreTransaction ->
val filteringSequence = engine.instantiateGetAll(Issues.CLASS).asSequence().filter {
it.id.typeId >= 0
}
OMultipleEntitiesIterable(currentTx, filteringSequence.toList())
}, "MultipleEntitiesIterable")
)
}
}
Expand Down Expand Up @@ -644,6 +651,37 @@ class OQueryEngineTest(
}
}

@Test
fun `should query by property sorted`() {
// Given
val test = givenTestCase()

val metadata = givenModelMetadata().withEntityMetaData(Issues.CLASS)
val engine = givenOQueryEngine(metadata)

// When
withStoreTx { tx ->
val sortByPropertyAsc = SortByProperty(
null, // child node
"name", // link property name
true // ascending
)
val issuesAsc = engine.query(iterableGetter(engine, tx), Issues.CLASS, sortByPropertyAsc)

val sortByLinkPropertyDesc = SortByProperty(
null, // child node
"name", // link property name
false // descending
)
val issuesDesc = engine.query(iterableGetter(engine, tx), Issues.CLASS, sortByLinkPropertyDesc)

// Then
// As sorted by project name
assertOrderedNamesExactly(issuesDesc, "issue3", "issue2", "issue1")
assertOrderedNamesExactly(issuesAsc, "issue1", "issue2", "issue3")
}
}

private fun assertOrderedNamesExactly(result: Iterable<Entity>, vararg names: String) {
assertThat(result.map { it.getProperty("name") }).containsExactly(*names).inOrder()
}
Expand Down
Loading