Skip to content

Commit

Permalink
feat: Query class
Browse files Browse the repository at this point in the history
test: SimpleCondition
  • Loading branch information
sepgh committed Nov 3, 2024
1 parent 33057fc commit 7d89112
Show file tree
Hide file tree
Showing 15 changed files with 651 additions and 25 deletions.
6 changes: 5 additions & 1 deletion src/main/java/com/github/sepgh/testudo/index/BinaryList.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void setLastItemIndex(int index) {
byte[] byteArray = Ints.toByteArray(index);
System.arraycopy(byteArray, 0, data, META_INDEX_END_CURSOR, byteArray.length);
}

private int getDbObjectSize() {
return this.data.length + DBObject.META_BYTES;
}
Expand Down Expand Up @@ -150,7 +151,10 @@ public void setObjectAt(int index, V v) {
public int binarySearchPosition(V v){
int low = 0;
int high = getLastItemIndex();
int mid = 0;
int mid;

if (high == -1)
return 0;

if (v.compareTo(getObjectAt(high)) > 0)
return high + 1;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/github/sepgh/testudo/index/Bitmap.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.sepgh.testudo.index;

import com.github.sepgh.testudo.operation.query.Order;
import com.google.common.primitives.UnsignedInteger;
import com.google.common.primitives.UnsignedLong;
import lombok.Getter;

Expand Down Expand Up @@ -245,6 +246,8 @@ private void moveToNextBit() {
protected K convertIndexToK(BigInteger index) {
if (UnsignedLong.class.isAssignableFrom(kClass)) {
return (K) UnsignedLong.valueOf(index); // Handle UnsignedLong
} else if (UnsignedInteger.class.isAssignableFrom(kClass)) {
return (K) UnsignedInteger.valueOf(index); // Handle UnsignedLong
} else if (Long.class.isAssignableFrom(kClass)) {
return (K) Long.valueOf(index.longValue()); // Handle UnsignedLong
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,23 @@ public boolean addIndex(K identifier, V value) throws InternalOperationException
if (dbObjectOptional.isEmpty()) {
throw new RuntimeException(); // Todo: it was pointing to somewhere without data
}
BinaryList<V> BinaryList = new BinaryList<>(engineConfig, valueIndexBinaryObjectFactory, dbObjectOptional.get().getData());
BinaryList<V> binaryList = new BinaryList<>(engineConfig, valueIndexBinaryObjectFactory, dbObjectOptional.get().getData());

int prevSize = binaryList.getData().length;
binaryList.addNew(value);
int afterSize = binaryList.getData().length;

int prevSize = BinaryList.getData().length;
BinaryList.addNew(value);
int afterSize = BinaryList.getData().length;

if (afterSize == prevSize) {
databaseStorageManager.update(pointer, dbObject -> {
try {
dbObject.modifyData(BinaryList.getData());
dbObject.modifyData(binaryList.getData());
} catch (VerificationException.InvalidDBObjectWrapper e) {
throw new RuntimeException(e); // Todo
}
});
} else {
Pointer pointerNew = databaseStorageManager.store(collectionId, -1, BinaryList.getData());
Pointer pointerNew = databaseStorageManager.store(collectionId, -1, binaryList.getData());
try {
indexManager.updateIndex(identifier, pointerNew);
} catch (IndexMissingException e) {
Expand All @@ -88,13 +89,12 @@ public boolean addIndex(K identifier, V value) throws InternalOperationException
// Creating new binary list iterator and add the object

byte[] bytes = new byte[BinaryList.META_SIZE + valueIndexBinaryObjectFactory.size() * 5]; // Todo: "5" here is just random! Need a better plan?
BinaryList<V> BinaryList = new BinaryList<>(engineConfig, valueIndexBinaryObjectFactory, bytes);
BinaryList.initialize();
BinaryList.addNew(value);
BinaryList<V> binaryList = new BinaryList<>(engineConfig, valueIndexBinaryObjectFactory, bytes);
binaryList.initialize();
binaryList.addNew(value);

// Insert to DB

Pointer pointer = databaseStorageManager.store(collectionId, -1, BinaryList.getData());
Pointer pointer = databaseStorageManager.store(collectionId, -1, binaryList.getData());
try {
this.indexManager.addIndex(identifier, pointer);
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ private void init() throws InternalOperationException {
leafTreeNode = BPlusTreeUtils.getResponsibleNode(indexStorageManager, getRoot(indexIOSession), identifier, indexId, degree, nodeFactory);
keyValueList = leafTreeNode.getKeyValueList(degree);

if (keyValueList.isEmpty()){
index = -1;
return;
}

if (operation == Operation.LT && keyValueList.getFirst().key().compareTo(identifier) >= 0 && leafTreeNode.getPreviousSiblingPointer(degree).isPresent()){
leafTreeNode = (AbstractLeafTreeNode<K, V>) indexIOSession.read(leafTreeNode.getPreviousSiblingPointer(degree).get());
keyValueList = leafTreeNode.getKeyValueList(degree);
Expand Down Expand Up @@ -369,6 +374,11 @@ private void init() throws InternalOperationException {
leafTreeNode = BPlusTreeUtils.getResponsibleNode(indexStorageManager, getRoot(indexIOSession), identifier, indexId, degree, nodeFactory);
keyValueList = leafTreeNode.getKeyValueList(degree);

if (keyValueList.isEmpty()){
index = -1;
return;
}

if (operation == Operation.GT && keyValueList.getLast().key().compareTo(identifier) <= 0 && leafTreeNode.getNextSiblingPointer(degree).isPresent()){
leafTreeNode = (AbstractLeafTreeNode<K, V>) indexIOSession.read(leafTreeNode.getNextSiblingPointer(degree).get());
keyValueList = leafTreeNode.getKeyValueList(degree);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.github.sepgh.testudo.operation;

import com.github.sepgh.testudo.index.DuplicateIndexManager;
import com.github.sepgh.testudo.index.DuplicateQueryableIndex;
import com.github.sepgh.testudo.index.Pointer;
import com.github.sepgh.testudo.index.UniqueQueryableIndex;
import com.github.sepgh.testudo.index.UniqueTreeIndexManager;
Expand All @@ -9,6 +9,6 @@

public interface CollectionIndexProvider {
UniqueQueryableIndex<?, ? extends Number> getUniqueIndexManager(Scheme.Field field);
DuplicateIndexManager<?, ? extends Number> getDuplicateIndexManager(Scheme.Field field);
DuplicateQueryableIndex<?, ? extends Number> getDuplicateIndexManager(Scheme.Field field);
UniqueTreeIndexManager<?, Pointer> getClusterIndexManager();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class DefaultCollectionIndexProviderFactory implements CollectionIndexPro
protected final Map<Scheme.Collection, CollectionIndexProvider> providers = new HashMap<>();
protected final Map<String, UniqueQueryableIndex<?, ? extends Number>> uniqueTreeIndexManagers = new HashMap<>();
protected final Map<String, UniqueTreeIndexManager<?, Pointer>> clusterIndexManagers = new HashMap<>();
protected final Map<String, DuplicateIndexManager<?, ? extends Number>> duplicateIndexManagers = new HashMap<>();
protected final Map<String, DuplicateQueryableIndex<?, ? extends Number>> duplicateIndexManagers = new HashMap<>();
protected final EngineConfig engineConfig;
protected final IndexStorageManagerFactory indexStorageManagerFactory;
protected final DatabaseStorageManager databaseStorageManager;
Expand All @@ -36,7 +36,7 @@ public CollectionIndexProvider create(Scheme.Collection collection) {
return providers.computeIfAbsent(collection, this::getProvider);
}

protected Scheme.Field getClusterField(Scheme.Collection collection) {
protected Scheme.Field getClusterField() {
return Scheme.Field.builder()
.id(-1)
.name("__CLUSTER_ID__")
Expand Down Expand Up @@ -65,13 +65,13 @@ protected String getIndexId(Scheme.Collection collection, Scheme.Field field){
engineConfig.getBTreeDegree(),
indexStorageManagerFactory.create(collection, field),
serializer.getIndexBinaryObjectFactory(field),
clusterSerializer.getIndexBinaryObjectFactory(getClusterField(collection))
clusterSerializer.getIndexBinaryObjectFactory(getClusterField())
);

}

protected UniqueTreeIndexManager<?, Pointer> buildClusterIndexManager(Scheme.Collection collection) {
Scheme.Field field = getClusterField(collection);
Scheme.Field field = getClusterField();
int indexId = getIndexId(collection, field).hashCode();
Serializer<?> serializer = SerializerRegistry.getInstance().getSerializer(field.getType());

Expand All @@ -83,7 +83,7 @@ protected UniqueTreeIndexManager<?, Pointer> buildClusterIndexManager(Scheme.Col
);
}

protected <K extends Comparable<K>, V extends Number & Comparable<V>> DuplicateIndexManager<K, V> buildDuplicateIndexManager(Scheme.Collection collection, Scheme.Field field) {
protected <K extends Comparable<K>, V extends Number & Comparable<V>> DuplicateQueryableIndex<K, V> buildDuplicateIndexManager(Scheme.Collection collection, Scheme.Field field) {
int indexId = getIndexId(collection, field).hashCode();

Serializer<?> fieldSerializer = SerializerRegistry.getInstance().getSerializer(field.getType());
Expand All @@ -102,15 +102,15 @@ protected <K extends Comparable<K>, V extends Number & Comparable<V>> DuplicateI
return new DuplicateBitmapIndexManager<>(
collection.getId(),
(UniqueQueryableIndex<K, Pointer>) uniqueTreeIndexManager,
(IndexBinaryObjectFactory<V>) clusterSerializer.getIndexBinaryObjectFactory(getClusterField(collection)),
(IndexBinaryObjectFactory<V>) clusterSerializer.getIndexBinaryObjectFactory(getClusterField()),
databaseStorageManager
);
}
return new DuplicateBPlusTreeIndexManagerBridge<>(
collection.getId(),
engineConfig,
(UniqueQueryableIndex<K, Pointer>) uniqueTreeIndexManager,
(IndexBinaryObjectFactory<V>) clusterSerializer.getIndexBinaryObjectFactory(getClusterField(collection)),
(IndexBinaryObjectFactory<V>) clusterSerializer.getIndexBinaryObjectFactory(getClusterField()),
databaseStorageManager
);
}
Expand All @@ -127,13 +127,13 @@ protected CollectionIndexProvider getProvider(Scheme.Collection collection) {
}

@Override
public DuplicateIndexManager<?, ?> getDuplicateIndexManager(Scheme.Field field) {
public DuplicateQueryableIndex<?, ?> getDuplicateIndexManager(Scheme.Field field) {
return duplicateIndexManagers.computeIfAbsent(getIndexId(collection, field), key -> buildDuplicateIndexManager(collection, field));
}

@Override
public UniqueTreeIndexManager<?, Pointer> getClusterIndexManager() {
return clusterIndexManagers.computeIfAbsent(getIndexId(collection, getClusterField(collection)), key -> buildClusterIndexManager(collection));
return clusterIndexManagers.computeIfAbsent(getIndexId(collection, getClusterField()), key -> buildClusterIndexManager(collection));
}
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.github.sepgh.testudo.operation.query;

import com.github.sepgh.testudo.operation.CollectionIndexProvider;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class CompositeCondition implements Condition {
private final CompositeOperator operator;
private final List<Condition> conditions = new ArrayList<>();
private final List<CompositeCondition> compositeConditions = new ArrayList<>();

public CompositeCondition(CompositeOperator operator, Condition... initialConditions) {
this.operator = operator;
for (Condition condition : initialConditions) {
addCondition(condition);
}
}

public CompositeCondition(CompositeOperator operator, CompositeCondition left, Condition right) {
this.operator = operator;
this.compositeConditions.add(left);
this.conditions.add(right);
}

public void addCondition(Condition condition) {
conditions.add(condition);
}

@Override
public <V extends Number & Comparable<V>> Iterator<V> evaluate(CollectionIndexProvider collectionIndexProvider, Order order) {
List<Iterator<V>> iterators = conditions.stream()
.map(cond -> (Iterator<V>) cond.evaluate(collectionIndexProvider, order))
.collect(Collectors.toList());
return new CompositeConditionIterator<>(operator, iterators, order); }

@Override
public String getField() {
throw new UnsupportedOperationException("Composite conditions do not have a single field");
}

public enum CompositeOperator {
AND, OR;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.github.sepgh.testudo.operation.query;

import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;

public class CompositeConditionIterator<T extends Comparable<T>> implements Iterator<T> {
private final CompositeCondition.CompositeOperator operator;
private final PriorityQueue<PeekableIterator<T>> iterators;
private T nextItem;

CompositeConditionIterator(CompositeCondition.CompositeOperator operator, List<Iterator<T>> iterators, Order order) {
this.operator = operator;
this.iterators = new PriorityQueue<>((a, b) -> order.equals(Order.ASC) ?
a.peek().compareTo(b.peek()) : b.peek().compareTo(a.peek()));

// Initialize the priority queue with each iterator's first element
for (Iterator<T> it : iterators) {
if (it.hasNext()) {
this.iterators.add(new PeekableIterator<>(it));
}
}
advance();
}

private void advance() {
if (operator == CompositeCondition.CompositeOperator.AND) {
advanceForAnd();
} else {
advanceForOr();
}
}

private void advanceForAnd() {
while (!iterators.isEmpty()) {
T candidate = iterators.peek().peek();
boolean allMatch = true;

for (PeekableIterator<T> it : iterators) {
while (it.hasNext() && !it.peek().equals(candidate)) {
it.next();
}
if (!it.hasNext() || !it.peek().equals(candidate)) {
allMatch = false;
break;
}
}

if (allMatch) {
nextItem = candidate;
iterators.forEach(PeekableIterator::next);
return;
}
}
nextItem = null;
}

private void advanceForOr() {
if (!iterators.isEmpty()) {
PeekableIterator<T> smallest = iterators.poll();
nextItem = smallest.next();
if (smallest.hasNext()) {
iterators.add(smallest);
}
} else {
nextItem = null;
}
}

@Override
public boolean hasNext() {
return nextItem != null;
}

@Override
public T next() {
T result = nextItem;
advance();
return result;
}


// PeekableIterator class for reference
private static class PeekableIterator<T> implements Iterator<T> {
private final Iterator<T> iterator;
private T next;

public PeekableIterator(Iterator<T> iterator) {
this.iterator = iterator;
if (iterator.hasNext()) next = iterator.next();
}

public T peek() {
return next;
}

@Override
public boolean hasNext() {
return next != null;
}

@Override
public T next() {
T current = next;
next = iterator.hasNext() ? iterator.next() : null;
return current;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.github.sepgh.testudo.operation.query;

import com.github.sepgh.testudo.operation.CollectionIndexProvider;

import java.util.Iterator;

public interface Condition {
<V extends Number & Comparable<V>> Iterator<V> evaluate(CollectionIndexProvider collectionIndexProvider, Order order);
String getField();
}
Loading

0 comments on commit 7d89112

Please sign in to comment.