Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #10 from deanhiller/master

merging deanhiller with easility
  • Loading branch information...
commit 58f7ee08ef717103ae8d9b36306b589c8f47e1e1 2 parents 5604265 + 2541320
@easility easility authored
Showing with 1,993 additions and 235 deletions.
  1. +0 −69 .classpath
  2. +15 −0 input/javasrc/com/alvazan/orm/api/base/CursorToManyImpl.java
  3. +4 −2 input/javasrc/com/alvazan/orm/api/z5api/NoSqlSession.java
  4. +2 −1  input/javasrc/com/alvazan/orm/api/z8spi/NoSqlRawSession.java
  5. +12 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/AbstractCursor.java
  6. +4 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/Cursor.java
  7. +4 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/DirectCursor.java
  8. +9 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/EmptyCursor.java
  9. +53 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/IndiceToVirtual.java
  10. +49 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/IterableWrappingCursor.java
  11. +51 −0 input/javasrc/com/alvazan/orm/api/z8spi/iter/ListWrappingCursor.java
  12. +22 −9 input/javasrc/com/alvazan/orm/api/z8spi/iter/ProxyTempCursor.java
  13. +0 −1  input/javasrc/com/alvazan/orm/api/z8spi/meta/ReflectionUtil.java
  14. +2 −1  input/javasrc/com/alvazan/orm/impl/meta/data/NoSqlProxyImpl.java
  15. +22 −4 input/javasrc/com/alvazan/orm/impl/meta/data/collections/CursorProxy.java
  16. +3 −2 input/javasrc/com/alvazan/orm/impl/meta/data/collections/MapProxyFetchAll.java
  17. +3 −2 input/javasrc/com/alvazan/orm/impl/meta/data/collections/OurAbstractCollection.java
  18. +17 −4 input/javasrc/com/alvazan/orm/layer0/base/BaseEntityManagerImpl.java
  19. +17 −0 input/javasrc/com/alvazan/orm/layer0/base/CursorRow.java
  20. +12 −0 input/javasrc/com/alvazan/orm/layer0/base/DebugCursor.java
  21. +1 −4 input/javasrc/com/alvazan/orm/layer0/base/QueryAdapter.java
  22. +52 −1 input/javasrc/com/alvazan/orm/layer3/typed/CursorAllViews.java
  23. +22 −0 input/javasrc/com/alvazan/orm/layer3/typed/CursorFillNulls.java
  24. +33 −0 input/javasrc/com/alvazan/orm/layer3/typed/CursorJoinedViews.java
  25. +13 −0 input/javasrc/com/alvazan/orm/layer3/typed/CursorProxyDirect.java
  26. +15 −0 input/javasrc/com/alvazan/orm/layer3/typed/CursorToIndexPoint.java
  27. +10 −0 input/javasrc/com/alvazan/orm/layer3/typed/CursorTypedResp.java
  28. +77 −0 input/javasrc/com/alvazan/orm/layer3/typed/IndiceCursorProxy.java
  29. +6 −5 input/javasrc/com/alvazan/orm/layer3/typed/NoSqlTypedSessionImpl.java
  30. +3 −2 input/javasrc/com/alvazan/orm/layer3/typed/QueryResultImpl.java
  31. +50 −0 input/javasrc/com/alvazan/orm/layer3/typed/TypedProxyWrappingCursor.java
  32. +2 −1  input/javasrc/com/alvazan/orm/layer5/nosql/cache/NoSqlReadCacheImpl.java
  33. +4 −2 input/javasrc/com/alvazan/orm/layer5/nosql/cache/NoSqlWriteCacheImpl.java
  34. +40 −3 input/javasrc/com/alvazan/orm/layer5/query/CachingCursor.java
  35. +82 −0 input/javasrc/com/alvazan/orm/layer5/query/CursorForAnd.java
  36. +67 −3 input/javasrc/com/alvazan/orm/layer5/query/CursorForJoin.java
  37. +58 −31 input/javasrc/com/alvazan/orm/layer5/query/CursorForOr.java
  38. +27 −5 input/javasrc/com/alvazan/orm/layer5/query/CursorForPrimaryKey.java
  39. +18 −0 input/javasrc/com/alvazan/orm/layer5/query/CursorSimpleTranslator.java
  40. +28 −3 input/javasrc/com/alvazan/orm/layer5/query/SpiIndexQueryImpl.java
  41. +35 −4 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CassandraSession.java
  42. +73 −10 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CursorColumnSlice.java
  43. +129 −11 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CursorKeysToRows2.java
  44. +42 −2 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CursorOfFutures.java
  45. +24 −0 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CursorResult.java
  46. +21 −10 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CursorReturnsEmptyRows.java
  47. +119 −0 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/OurColumnListIterator.java
  48. +5 −2 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/StartQueryManyKeys.java
  49. +2 −1  input/javasrc/com/alvazan/orm/layer9z/spi/db/hadoop/HadoopSession.java
  50. +153 −21 input/javasrc/com/alvazan/orm/layer9z/spi/db/inmemory/CursorKeysToRows.java
  51. +4 −3 input/javasrc/com/alvazan/orm/layer9z/spi/db/inmemory/InMemorySession.java
  52. +2 −1  input/javasrc/com/alvazan/orm/logging/NoSqlDevLogger.java
  53. +2 −1  input/javasrc/com/alvazan/orm/logging/NoSqlRawLogger.java
  54. +19 −3 input/javasrc/com/alvazan/orm/parser/antlr/ExpressionNode.java
  55. +7 −1 input/javasrc/com/alvazan/orm/parser/antlr/OptimizeAddJoinInfo.java
  56. +7 −1 input/javasrc/com/alvazan/orm/parser/antlr/ParsedNode.java
  57. +30 −0 input/javasrc/com/alvazan/orm/parser/antlr/ScannerSql.java
  58. +34 −0 input/javasrc/com/alvazan/play/logging/LogDao.java
  59. +1 −0  input/javasrc/com/alvazan/test/FactorySingleton.java
  60. +8 −0 input/javasrc/com/alvazan/test/TestGrammar.java
  61. +19 −1 input/javasrc/com/alvazan/test/TestIndexAndOrParens.java
  62. +33 −0 input/javasrc/com/alvazan/test/TestIndexes.java
  63. +235 −0 input/javasrc/com/alvazan/test/TestJoins.java
  64. +24 −1 input/javasrc/com/alvazan/test/TestOneToMany.java
  65. +41 −1 input/javasrc/com/alvazan/test/db/Account.java
  66. +15 −6 input/schemas/NoSql.g
View
69 .classpath
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="input/javasrc"/>
- <classpathentry kind="src" path="output/src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib" path="input/libexclude/junit.jar"/>
- <classpathentry kind="lib" path="input/libexclude/play-1.2.x-dcdb1f3.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/antlr-jar-2.7.7.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/antlr-jar-3.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/antlr-runtime-jar-3.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/avro-jar-1.4.0-cassandra-1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/commons-cli-jar-1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/commons-codec-jar-1.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/commons-lang-jar-2.4.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/commons-logging-jar-1.1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/compress-lzf-bundle-0.8.4.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/concurrentlinkedhashmap-lru-jar-1.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/high-scale-lib-jar-1.1.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/httpclient-jar-4.0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/httpcore-jar-4.0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jamm-jar-0.2.5.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jetty-jar-6.1.22.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jetty-util-jar-6.1.22.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jline-jar-0.9.94.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/joda-time-jar-2.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/json-simple-jar-1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/libthrift-jar-0.7.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/metrics-core-jar-2.0.3.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/org.apache.servicemix.bundles.commons-csv-bundle-1.0-r706900_3.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/servlet-api-jar-2.5-20081211.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/servlet-api-jar-2.5.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/slf4j-api-jar-1.6.4.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/snakeyaml-jar-1.6.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/snappy-java-bundle-1.0.4.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/snaptree-jar-0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/stax-api-jar-1.0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/stringtemplate-jar-3.2.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/junit-jar-4.9.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/javassist-jar-3.16.1-GA.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/activation-jar-1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/aopalliance-jar-1.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/args4j-jar-2.0.16.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/asm-jar-3.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/cglib-jar-2.2.1-v20090111.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/geronimo-jms_1.1_spec-jar-1.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/groovy-all-jar-1.7.6.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/guice-jar-3.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/guice-javadoc-3.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/guice-source-3.0.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/hamcrest-core-jar-1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/janino-jar-2.5.16.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/javax.inject-jar-1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/logback-classic-jar-1.0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/logback-core-jar-1.0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/mail-jar-1.4.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/servlet-api-jar-2.5.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-inmemory/slf4j-api-jar-1.6.4.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jsr305-jar-1.3.9.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/astyanax-jar-1.56.18.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/cassandra-all-jar-1.1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/cassandra-thrift-jar-1.1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/guava-jar-11.0.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jackson-core-asl-jar-1.9.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jackson-mapper-asl-jar-1.9.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/jettison-bundle-1.2.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/joda-convert-jar-1.1.jar"/>
- <classpathentry kind="lib" path="output/jardist/playorm-astyanax/uuid-jar-3.2.jar"/>
- <classpathentry kind="output" path="eclipsegen"/>
-</classpath>
View
15 input/javasrc/com/alvazan/orm/api/base/CursorToManyImpl.java
@@ -27,6 +27,13 @@ public CursorToManyImpl(List<T> elements) {
public void beforeFirst() {
index = -1;
}
+
+ @Override
+ public void afterLast() {
+ index = -1;
+ if (list!=null)
+ index=list.size();
+ }
@Override
public boolean next() {
@@ -35,6 +42,14 @@ public boolean next() {
return true;
return false;
}
+
+ @Override
+ public boolean previous() {
+ index--;
+ if(index >= 0)
+ return true;
+ return false;
+ }
@Override
public T getCurrent() {
View
6 input/javasrc/com/alvazan/orm/api/z5api/NoSqlSession.java
@@ -12,6 +12,7 @@
import com.alvazan.orm.api.z8spi.action.Column;
import com.alvazan.orm.api.z8spi.action.IndexColumn;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.layer5.nosql.cache.NoSqlWriteCacheImpl;
import com.google.inject.ImplementedBy;
@@ -53,7 +54,7 @@
public void removeColumn(DboTableMeta colFamily, byte[] rowKey, byte[] columnName);
- public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily, Iterable<byte[]> rowKeys, boolean skipReadCache, boolean cacheResults, Integer batchSize);
+ public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily, DirectCursor<byte[]> rowKeys, boolean skipReadCache, boolean cacheResults, Integer batchSize);
public Row find(DboTableMeta colFamily, byte[] rowKey);
@@ -75,7 +76,8 @@
* @return
*/
public AbstractCursor<IndexColumn> scanIndex(ScanInfo info, Key from, Key to, Integer batchSize);
- public AbstractCursor<IndexColumn> scanIndex(ScanInfo scanInfo, List<byte[]> values);
+ public AbstractCursor<IndexColumn> scanIndex(ScanInfo scanInfo, List<byte[]> values);
+
public AbstractCursor<Column> columnSlice(DboTableMeta colFamily, byte[] rowKey, byte[] from, byte[] to, Integer batchSize);
View
3  input/javasrc/com/alvazan/orm/api/z8spi/NoSqlRawSession.java
@@ -7,6 +7,7 @@
import com.alvazan.orm.api.z8spi.action.Column;
import com.alvazan.orm.api.z8spi.action.IndexColumn;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
@@ -40,7 +41,7 @@
public AbstractCursor<IndexColumn> scanIndex(ScanInfo scanInfo, List<byte[]> values, BatchListener list, MetaLookup mgr);
- public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily, Iterable<byte[]> rowKeys, Cache cache, int batchSize, BatchListener list, MetaLookup mgr);
+ public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily, DirectCursor<byte[]> rowKeys, Cache cache, int batchSize, BatchListener list, MetaLookup mgr);
public void readMetaAndCreateTable(MetaLookup ormSession, String colFamily);
View
12 input/javasrc/com/alvazan/orm/api/z8spi/iter/AbstractCursor.java
@@ -14,8 +14,20 @@ public final boolean next() {
}
return true;
}
+
+ @Override
+ public final boolean previous() {
+ currentValue = previousImpl();
+ if(currentValue == null) {
+ //There is NO previous value so screw it, return false
+ return false;
+ }
+ return true;
+ }
public abstract Holder<T> nextImpl();
+
+ public abstract Holder<T> previousImpl();
@Override
public final T getCurrent() {
View
4 input/javasrc/com/alvazan/orm/api/z8spi/iter/Cursor.java
@@ -10,5 +10,9 @@
boolean next();
T getCurrent();
+
+ void afterLast();
+
+ boolean previous();
}
View
4 input/javasrc/com/alvazan/orm/api/z8spi/iter/DirectCursor.java
@@ -5,7 +5,11 @@
public interface DirectCursor<T> {
public Holder<T> nextImpl();
+
+ public Holder<T> previousImpl();
public void beforeFirst();
+ public void afterLast();
+
}
View
9 input/javasrc/com/alvazan/orm/api/z8spi/iter/EmptyCursor.java
@@ -11,6 +11,15 @@ public void beforeFirst() {
public com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<T> nextImpl() {
return null;
}
+
+ @Override
+ public void afterLast() {
+ }
+
+ @Override
+ public com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<T> previousImpl() {
+ return null;
+ }
}
View
53 input/javasrc/com/alvazan/orm/api/z8spi/iter/IndiceToVirtual.java
@@ -0,0 +1,53 @@
+package com.alvazan.orm.api.z8spi.iter;
+
+import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
+
+public class IndiceToVirtual implements DirectCursor<byte[]> {
+
+ private DboTableMeta meta;
+ private DirectCursor<byte[]> noSqlKeys;
+
+ public IndiceToVirtual(DboTableMeta meta, DirectCursor<byte[]> noSqlKeys) {
+ this.meta = meta;
+ this.noSqlKeys = noSqlKeys;
+ }
+
+ @Override
+ public String toString() {
+ String tabs = StringLocal.getAndAdd();
+ String retVal = "IndiceToVirtual(keyToVirtualKeyTranslatorCursor)["+tabs+noSqlKeys+tabs+"]";
+ StringLocal.set(tabs.length());
+ return retVal;
+ }
+
+
+ @Override
+ public Holder<byte[]> nextImpl() {
+ Holder<byte[]> nextHolder = noSqlKeys.nextImpl();
+ if (nextHolder == null)
+ return null;
+ byte[] next = nextHolder.getValue();
+ return new Holder<byte[]>(meta.getIdColumnMeta().formVirtRowKey(next));
+ }
+
+ @Override
+ public Holder<byte[]> previousImpl() {
+ Holder<byte[]> nextHolder = noSqlKeys.previousImpl();
+ if (nextHolder == null)
+ return null;
+ byte[] next = nextHolder.getValue();
+ return new Holder<byte[]>(meta.getIdColumnMeta().formVirtRowKey(next));
+ }
+
+ @Override
+ public void beforeFirst() {
+ noSqlKeys.beforeFirst();
+
+ }
+
+ @Override
+ public void afterLast() {
+ noSqlKeys.afterLast();
+ }
+}
View
49 input/javasrc/com/alvazan/orm/api/z8spi/iter/IterableWrappingCursor.java
@@ -0,0 +1,49 @@
+package com.alvazan.orm.api.z8spi.iter;
+
+import java.util.Iterator;
+
+import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+
+public class IterableWrappingCursor<T> implements DirectCursor<T> {
+
+ private Iterable<T> iter;
+ private Iterator<T> currentIterator;
+
+ public IterableWrappingCursor(Iterable<T> iter) {
+ this.iter = iter;
+ }
+
+ @Override
+ public String toString() {
+ String tabs = StringLocal.getAndAdd();
+ String retVal = "IteratorWrappingCursor(iteratorWrappingCursor)["+tabs+iter+tabs+"]";
+ StringLocal.set(tabs.length());
+ return retVal;
+ }
+
+
+ @Override
+ public Holder<T> nextImpl() {
+ if (currentIterator == null)
+ beforeFirst();
+ if (!currentIterator.hasNext())
+ return null;
+ return new Holder<T>(currentIterator.next());
+ }
+
+ @Override
+ public Holder<T> previousImpl() {
+ throw new UnsupportedOperationException("We can't go backward on a cursor that is wrapping an iterator");
+ }
+
+ @Override
+ public void beforeFirst() {
+ currentIterator = iter.iterator();
+
+ }
+
+ @Override
+ public void afterLast() {
+ throw new UnsupportedOperationException("We can't go backward on a cursor that is wrapping an iterator");
+ }
+}
View
51 input/javasrc/com/alvazan/orm/api/z8spi/iter/ListWrappingCursor.java
@@ -0,0 +1,51 @@
+package com.alvazan.orm.api.z8spi.iter;
+
+import java.util.List;
+import java.util.ListIterator;
+
+import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+
+public class ListWrappingCursor<T> implements DirectCursor<T> {
+
+ private List<T> backingList;
+ private ListIterator<T> backingListIterator;
+
+ public ListWrappingCursor(List<T> list) {
+ backingList = list;
+ this.backingListIterator = list.listIterator();
+ }
+
+ @Override
+ public String toString() {
+ String tabs = StringLocal.getAndAdd();
+ String retVal = "ListWrappingCursor(ListWrappingCursor)["+tabs+backingListIterator+tabs+"]";
+ StringLocal.set(tabs.length());
+ return retVal;
+ }
+
+
+ @Override
+ public Holder<T> nextImpl() {
+ if (backingListIterator.hasNext())
+ return new Holder<T>(backingListIterator.next());
+ return null;
+ }
+
+ @Override
+ public Holder<T> previousImpl() {
+ if (backingListIterator.hasPrevious())
+ return new Holder<T>(backingListIterator.previous());
+ return null;
+ }
+
+ @Override
+ public void beforeFirst() {
+ backingListIterator = backingList.listIterator();
+ }
+
+ @Override
+ public void afterLast() {
+ while (backingListIterator.hasNext())
+ backingListIterator.next();
+ }
+}
View
31 input/javasrc/com/alvazan/orm/api/z8spi/iter/ProxyTempCursor.java
@@ -1,37 +1,50 @@
package com.alvazan.orm.api.z8spi.iter;
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.ListIterator;
public class ProxyTempCursor<T> extends AbstractCursor<T> {
- private Iterable<T> iterable;
- private Iterator<T> iterator;
+ private ListIterator<T> items;
- public ProxyTempCursor(Iterable<T> iterable) {
- this.iterable = iterable;
+ public ProxyTempCursor(Collection<T> items) {
+ this.items=new ArrayList<T>(items).listIterator();
beforeFirst();
}
@Override
public String toString() {
String tabs = StringLocal.getAndAdd();
- String retVal = "ProxyTempCursor["+tabs+iterable+tabs+"]";
+ String retVal = "ProxyTempCursor["+tabs+items+tabs+"]";
StringLocal.set(tabs.length());
return retVal;
}
@Override
public void beforeFirst() {
- iterator = iterable.iterator();
+ while(items.hasPrevious()) items.previous();
+ }
+
+ @Override
+ public void afterLast() {
+ while(items.hasNext()) items.next();
}
@Override
public com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<T> nextImpl() {
- if(!iterator.hasNext())
+ if(!items.hasNext())
+ return null;
+ return new Holder<T>(items.next());
+ }
+
+ @Override
+ public com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<T> previousImpl() {
+ if(!items.hasPrevious())
return null;
- return new Holder<T>(iterator.next());
+ return new Holder<T>(items.previous());
}
}
View
1  input/javasrc/com/alvazan/orm/api/z8spi/meta/ReflectionUtil.java
@@ -23,7 +23,6 @@ public static void putFieldValue(Object entity, Field field, Object value) {
//did entity.id get modified, BUT entity.nameToValue ALSO was modified for some dang
//reason and I am not sure why, so NOW instead of using field.set on javassist.util.Proxy
//we are going to call a special method on the Proxy to try to set the field instead
-
field.set(entity, value);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
View
3  input/javasrc/com/alvazan/orm/impl/meta/data/NoSqlProxyImpl.java
@@ -19,6 +19,7 @@
import com.alvazan.orm.api.z8spi.conv.Converter;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+import com.alvazan.orm.api.z8spi.iter.IterableWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnIdMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.impl.meta.data.collections.CacheLoadCallback;
@@ -119,7 +120,7 @@ private void fillInThisOneInstance(T self) {
List<byte[]> rowKeys = new ArrayList<byte[]>();
rowKeys.add(virtKey);
- AbstractCursor<KeyValue<Row>> rows = session.find(metaDbo, rowKeys, false, true, null);
+ AbstractCursor<KeyValue<Row>> rows = session.find(metaDbo, new IterableWrappingCursor<byte[]>(rowKeys), false, true, null);
Holder<KeyValue<Row>> holder = rows.nextImpl();
if(holder == null)
throw new RowNotFoundException("row for type="+classMeta.getMetaClass().getName()+" not found for key="+entityId);
View
26 input/javasrc/com/alvazan/orm/impl/meta/data/collections/CursorProxy.java
@@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import com.alvazan.orm.api.base.CursorToMany;
import com.alvazan.orm.api.z5api.NoSqlSession;
@@ -11,7 +12,8 @@
import com.alvazan.orm.api.z8spi.action.IndexColumn;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
-import com.alvazan.orm.api.z8spi.iter.IterToVirtual;
+import com.alvazan.orm.api.z8spi.iter.IndiceToVirtual;
+import com.alvazan.orm.api.z8spi.iter.ListWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.impl.meta.data.MetaAbstractClass;
import com.alvazan.orm.impl.meta.data.Tuple;
@@ -22,7 +24,7 @@
private NoSqlSession session;
private MetaAbstractClass<T> proxyMeta;
private int batchSize;
- private Iterator<T> cachedProxies;
+ private ListIterator<T> cachedProxies;
private T currentProxy;
private List<T> proxyList;
private List<byte[]> keyList;
@@ -45,6 +47,11 @@ public CursorProxy(Object owner, NoSqlSession session,
public void beforeFirst() {
cursor.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ cursor.afterLast();
+ }
@Override
public boolean next() {
@@ -56,6 +63,17 @@ public boolean next() {
currentProxy = null;
return false;
}
+
+ @Override
+ public boolean previous() {
+ loadSomeKeys();
+ if(cachedProxies.hasPrevious()) {
+ currentProxy = cachedProxies.previous();
+ return true;
+ }
+ currentProxy = null;
+ return false;
+ }
private void loadSomeKeys() {
if(cachedProxies != null && cachedProxies.hasNext())
@@ -78,7 +96,7 @@ private void loadSomeKeys() {
break;
}
- cachedProxies = proxyList.iterator();
+ cachedProxies = proxyList.listIterator();
//new proxies that are not initialized...
currentCacheLoaded = false;
}
@@ -103,7 +121,7 @@ private void loadCache() {
currentCacheLoaded = true;
DboTableMeta metaDbo = proxyMeta.getMetaDbo();
- Iterable<byte[]> virtKeys = new IterToVirtual(metaDbo, keyList);
+ IndiceToVirtual virtKeys = new IndiceToVirtual(metaDbo, new ListWrappingCursor<byte[]>(keyList));
AbstractCursor<KeyValue<Row>> rows = session.find(metaDbo, virtKeys, true, false, batchSize);
int counter = 0;
View
5 input/javasrc/com/alvazan/orm/impl/meta/data/collections/MapProxyFetchAll.java
@@ -17,7 +17,8 @@
import com.alvazan.orm.api.z8spi.Row;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
-import com.alvazan.orm.api.z8spi.iter.IterToVirtual;
+import com.alvazan.orm.api.z8spi.iter.IndiceToVirtual;
+import com.alvazan.orm.api.z8spi.iter.ListWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnIdMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.impl.meta.data.MetaAbstractClass;
@@ -62,7 +63,7 @@ public void loadCacheIfNeeded() {
DboTableMeta metaDbo = classMeta.getMetaDbo();
DboColumnIdMeta idMeta = metaDbo.getIdColumnMeta();
- Iterable<byte[]> virtKeys = new IterToVirtual(metaDbo, keys);
+ IndiceToVirtual virtKeys = new IndiceToVirtual(metaDbo, new ListWrappingCursor<byte[]>(keys));
AbstractCursor<KeyValue<Row>> rows = session.find(metaDbo, virtKeys, false, true, null);
String name = getClass().getSimpleName();
View
5 input/javasrc/com/alvazan/orm/impl/meta/data/collections/OurAbstractCollection.java
@@ -14,7 +14,8 @@
import com.alvazan.orm.api.z8spi.KeyValue;
import com.alvazan.orm.api.z8spi.Row;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
-import com.alvazan.orm.api.z8spi.iter.IterToVirtual;
+import com.alvazan.orm.api.z8spi.iter.IndiceToVirtual;
+import com.alvazan.orm.api.z8spi.iter.ListWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnIdMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.impl.meta.data.MetaAbstractClass;
@@ -63,7 +64,7 @@ public void loadCacheIfNeeded() {
DboTableMeta metaDbo = metaClass.getMetaDbo();
DboColumnIdMeta idMeta = metaDbo.getIdColumnMeta();
- Iterable<byte[]> virtKeys = new IterToVirtual(metaDbo, keys);
+ IndiceToVirtual virtKeys = new IndiceToVirtual(metaDbo, new ListWrappingCursor<byte[]>(keys));
AbstractCursor<KeyValue<Row>> rows = session.find(metaDbo, virtKeys, false, true, null);
String name = getClass().getSimpleName();
log.info(name+":just loaded rows for keylist(next convert to proxies)="+keys.size()+" for field="+field);
View
21 input/javasrc/com/alvazan/orm/layer0/base/BaseEntityManagerImpl.java
@@ -11,6 +11,7 @@
import com.alvazan.orm.api.base.NoSqlEntityManager;
import com.alvazan.orm.api.base.Query;
import com.alvazan.orm.api.z3api.NoSqlTypedSession;
+import com.alvazan.orm.api.z5api.IndexColumnInfo;
import com.alvazan.orm.api.z5api.NoSqlSession;
import com.alvazan.orm.api.z5api.SpiMetaQuery;
import com.alvazan.orm.api.z5api.SpiQueryAdapter;
@@ -22,17 +23,22 @@
import com.alvazan.orm.api.z8spi.conv.StorageTypeEnum;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.Cursor;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
+import com.alvazan.orm.api.z8spi.iter.IndiceToVirtual;
import com.alvazan.orm.api.z8spi.iter.IterToVirtual;
+import com.alvazan.orm.api.z8spi.iter.IterableWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnIdMeta;
import com.alvazan.orm.api.z8spi.meta.DboColumnMeta;
import com.alvazan.orm.api.z8spi.meta.DboDatabaseMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.api.z8spi.meta.IndexData;
import com.alvazan.orm.api.z8spi.meta.RowToPersist;
+import com.alvazan.orm.api.z8spi.meta.ViewInfo;
import com.alvazan.orm.impl.meta.data.MetaClass;
import com.alvazan.orm.impl.meta.data.MetaIdField;
import com.alvazan.orm.impl.meta.data.MetaInfo;
import com.alvazan.orm.impl.meta.data.NoSqlProxy;
+import com.alvazan.orm.layer3.typed.IndiceCursorProxy;
import com.alvazan.orm.layer3.typed.NoSqlTypedSessionImpl;
public class BaseEntityManagerImpl implements NoSqlEntityManager, MetaLookup, MetaLoader {
@@ -145,19 +151,26 @@ private void putImpl(Object originalEntity, boolean needRead, MetaClass metaClas
throw new IllegalArgumentException("Class type="+entityType.getName()+" was not found, please check that you scanned the right package and look at the logs to see if this class was scanned");
Iterable<byte[]> iter = new IterableKey<T>(meta, keys);
+ Iterable<byte[]> virtKeys = new IterToVirtual(meta.getMetaDbo(), iter);
//we pass in null for batch size such that we do infinite size or basically all keys passed into this method in one
//shot
- return findAllImpl2(meta, iter, null, true, null);
+ return findAllImpl2(meta, new IterableWrappingCursor<byte[]>(virtKeys), null, true, null);
}
- <T> AbstractCursor<KeyValue<T>> findAllImpl2(MetaClass<T> meta, Iterable<byte[]> iter, String query, boolean cacheResults, Integer batchSize) {
+ <T> AbstractCursor<KeyValue<T>> findAllImpl2(MetaClass<T> meta, ViewInfo mainView, DirectCursor<IndexColumnInfo> keys, String query, boolean cacheResults, Integer batchSize) {
//OKAY, so this gets interesting. The noSqlKeys could be a proxy iterable to
//millions of keys with some batch size. We canNOT do a find inline here but must do the find in
//batches as well
- Iterable<byte[]> virtKeys = new IterToVirtual(meta.getMetaDbo(), iter);
+ IndiceCursorProxy indiceCursor = new IndiceCursorProxy(mainView, keys);
+ DirectCursor<byte[]> virtKeys = new IndiceToVirtual(meta.getMetaDbo(), indiceCursor);
+ return findAllImpl2(meta, virtKeys, query, cacheResults, batchSize);
+ }
+
+
+ <T> AbstractCursor<KeyValue<T>> findAllImpl2(MetaClass<T> meta, DirectCursor<byte[]> keys, String query, boolean cacheResults, Integer batchSize) {
boolean skipCache = query != null;
- AbstractCursor<KeyValue<Row>> cursor = session.find(meta.getMetaDbo(), virtKeys, skipCache, cacheResults, batchSize);
+ AbstractCursor<KeyValue<Row>> cursor = session.find(meta.getMetaDbo(), keys, skipCache, cacheResults, batchSize);
return new CursorRow<T>(session, meta, cursor, query);
}
View
17 input/javasrc/com/alvazan/orm/layer0/base/CursorRow.java
@@ -29,6 +29,12 @@ public void beforeFirst() {
cursor.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ cursor.afterLast();
+ }
+
@Override
public Holder<KeyValue<T>> nextImpl() {
Holder<KeyValue<Row>> nextImpl = cursor.nextImpl();
@@ -40,6 +46,17 @@ public void beforeFirst() {
return new Holder<KeyValue<T>>(result);
}
+ @Override
+ public Holder<KeyValue<T>> previousImpl() {
+ Holder<KeyValue<Row>> prevImpl = cursor.previousImpl();
+ if(prevImpl == null)
+ return null;
+ KeyValue<Row> kv = prevImpl.getValue();
+
+ KeyValue<T> result = translateRow(kv);
+ return new Holder<KeyValue<T>>(result);
+ }
+
@SuppressWarnings("rawtypes")
private KeyValue<T> translateRow(KeyValue<Row> kv) {
Row row = kv.getValue();
View
12 input/javasrc/com/alvazan/orm/layer0/base/DebugCursor.java
@@ -17,6 +17,11 @@ public DebugCursor(DirectCursor<IndexColumnInfo> cursor) {
public Holder<IndexColumnInfo> nextImpl() {
return cursor.nextImpl();
}
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ return cursor.previousImpl();
+ }
@Override
public void beforeFirst() {
@@ -24,5 +29,12 @@ public void beforeFirst() {
throw new IllegalArgumentException("This cursor cannot be reset");
alreadyRan = true;
}
+
+ @Override
+ public void afterLast() {
+ if(alreadyRan)
+ throw new IllegalArgumentException("This cursor cannot be reset");
+ alreadyRan = true;
+ }
}
View
5 input/javasrc/com/alvazan/orm/layer0/base/QueryAdapter.java
@@ -30,7 +30,6 @@
import com.alvazan.orm.impl.meta.data.MetaClass;
import com.alvazan.orm.impl.meta.data.MetaField;
import com.alvazan.orm.impl.meta.data.MetaInfo;
-import com.alvazan.orm.layer3.typed.IterableCursorProxy;
import com.alvazan.orm.layer3.typed.IterableProxy;
public class QueryAdapter<T> implements Query<T> {
@@ -130,10 +129,8 @@ public T getSingleObject() {
//BIG NOTE: Here, we could return all the keys from the join so we can eagerly fetch other entities as well
//instead of waiting for the user to loop through those entities AND if user accesses those entites, we could block
//while the load is happening too in the background
- Iterable<byte[]> keys = new IterableCursorProxy(mainView, indice);
-
String query = meta.getQuery();
- AbstractCursor<KeyValue<T>> results = mgr.findAllImpl2(mainMetaClass, keys, query, cacheResults, batchSize);
+ AbstractCursor<KeyValue<T>> results = mgr.findAllImpl2(mainMetaClass, mainView, indice, query, cacheResults, batchSize);
return results;
}
View
53 input/javasrc/com/alvazan/orm/layer3/typed/CursorAllViews.java
@@ -11,6 +11,7 @@
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.iter.EmptyCursor;
+import com.alvazan.orm.api.z8spi.iter.IterableWrappingCursor;
import com.alvazan.orm.api.z8spi.iter.StringLocal;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.api.z8spi.meta.TypedRow;
@@ -50,6 +51,12 @@ public void beforeFirst() {
cachedCursors = new EmptyCursor<List<TypedRow>>();
cursor.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ cachedCursors = new EmptyCursor<List<TypedRow>>();
+ cursor.afterLast();
+ }
@Override
public Holder<List<TypedRow>> nextImpl() {
@@ -62,11 +69,28 @@ public void beforeFirst() {
return cachedCursors.nextImpl();
}
+
+ @Override
+ public Holder<List<TypedRow>> previousImpl() {
+ Holder<List<TypedRow>> previous = cachedCursors.previousImpl();
+ if(previous != null)
+ return previous;
+
+ //Well, the cursor ran out, load more results if any exist...
+ loadCacheBackward();
+
+ return cachedCursors.previousImpl();
+ }
private void loadCache() {
Map<ViewInfo, TwoLists> map = setupKeyLists();
createCursors(map);
}
+
+ private void loadCacheBackward() {
+ Map<ViewInfo, TwoLists> map = setupKeyListsBackward();
+ createCursors(map);
+ }
private void createCursors(Map<ViewInfo, TwoLists> map) {
List<DirectCursor<KeyValue<TypedRow>>> cursors = new ArrayList<DirectCursor<KeyValue<TypedRow>>>();
@@ -76,7 +100,7 @@ private void createCursors(Map<ViewInfo, TwoLists> map) {
TwoLists twoLists = map.get(view);
List<byte[]> rowKeys = twoLists.getListWithNoNulls();
DboTableMeta meta = view.getTableMeta();
- DirectCursor<KeyValue<TypedRow>> cursor = session.findAllImpl2(meta, null, rowKeys, query, batchSize);
+ DirectCursor<KeyValue<TypedRow>> cursor = session.findAllImpl2(meta, null, new IterableWrappingCursor<byte[]>(rowKeys), query, batchSize);
DirectCursor<KeyValue<TypedRow>> fillCursor = new CursorFillNulls(cursor, twoLists.getFullKeyList(), view);
cursors.add(fillCursor);
fullKeyLists.add(twoLists.getFullKeyList());
@@ -101,6 +125,33 @@ private void createCursors(Map<ViewInfo, TwoLists> map) {
IndexColumnInfo index = next.getValue();
+ if(index != null) {
+ for(ViewInfo info : eagerlyJoinedViews) {
+ byte[] pk = index.getPrimaryKeyRaw(info);
+ TwoLists twoLists = map.get(info);
+ twoLists.getFullKeyList().add(pk);
+ if(pk != null) {
+ List<byte[]> list = twoLists.getListWithNoNulls();
+ list.add(pk);
+ }
+ }
+ }
+ }
+ return map;
+ }
+
+ private Map<ViewInfo, TwoLists> setupKeyListsBackward() {
+ Map<ViewInfo, TwoLists> map = new HashMap<ViewInfo, TwoLists>();
+ initializeMap(map);
+
+ for(int i = 0; i < batchSize; i++) {
+ //Here we want to read in batchSize
+ Holder<IndexColumnInfo> previous = cursor.previousImpl();
+ if(previous == null)
+ break;
+
+
+ IndexColumnInfo index = previous.getValue();
for(ViewInfo info : eagerlyJoinedViews) {
byte[] pk = index.getPrimaryKeyRaw(info);
TwoLists twoLists = map.get(info);
View
22 input/javasrc/com/alvazan/orm/layer3/typed/CursorFillNulls.java
@@ -39,11 +39,33 @@ public CursorFillNulls(DirectCursor<KeyValue<TypedRow>> cursor,
return cursor.nextImpl();
}
+
+ @Override
+ public Holder<KeyValue<TypedRow>> previousImpl() {
+ if(!keyIter.hasNext())
+ return null;
+
+ byte[] theKey = keyIter.next();
+ if(theKey == null) {
+ KeyValue<TypedRow> kv = new KeyValue<TypedRow>();
+ TypedRow row = new TypedRow(view, view.getTableMeta());
+ kv.setValue(row);
+ return new Holder<KeyValue<TypedRow>>(kv);
+ }
+
+ return cursor.nextImpl();
+ }
@Override
public void beforeFirst() {
cursor.beforeFirst();
keyIter = fullKeyList.iterator();
}
+
+ @Override
+ public void afterLast() {
+ cursor.afterLast();
+ keyIter = fullKeyList.iterator();
+ }
}
View
33 input/javasrc/com/alvazan/orm/layer3/typed/CursorJoinedViews.java
@@ -29,6 +29,13 @@ public void beforeFirst() {
d.beforeFirst();
}
}
+
+ @Override
+ public void afterLast() {
+ for(DirectCursor<KeyValue<TypedRow>> d : cursors) {
+ d.afterLast();
+ }
+ }
@Override
public Holder<List<TypedRow>> nextImpl() {
@@ -55,4 +62,30 @@ public void beforeFirst() {
return new Holder<List<TypedRow>>(rows);
return null;
}
+
+ @Override
+ public Holder<List<TypedRow>> previousImpl() {
+ boolean atLeastOneCursorHasNext = false;
+ List<TypedRow> rows = new ArrayList<TypedRow>();
+ for(int i = 0; i < cursors.size(); i++) {
+ DirectCursor<KeyValue<TypedRow>> cursor = cursors.get(i);
+ ViewInfo view = views.get(i);
+ Holder<KeyValue<TypedRow>> next = cursor.previousImpl();
+ if(next != null) {
+ atLeastOneCursorHasNext = true;
+ KeyValue<TypedRow> kv = next.getValue();
+ TypedRow row = kv.getValue();
+ if(row != null)
+ row.setView(view);
+ rows.add(row);
+ } else {
+ TypedRow row = new TypedRow(view, view.getTableMeta());
+ rows.add(row);
+ }
+ }
+
+ if(atLeastOneCursorHasNext)
+ return new Holder<List<TypedRow>>(rows);
+ return null;
+ }
}
View
13 input/javasrc/com/alvazan/orm/layer3/typed/CursorProxyDirect.java
@@ -27,6 +27,11 @@ public String toString() {
public void beforeFirst() {
iter.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ iter.afterLast();
+ }
@Override
public boolean next() {
@@ -35,6 +40,14 @@ public boolean next() {
return false;
return true;
}
+
+ @Override
+ public boolean previous() {
+ cached = iter.previousImpl();
+ if(cached == null)
+ return false;
+ return true;
+ }
@Override
public IndexColumnInfo getCurrent() {
View
15 input/javasrc/com/alvazan/orm/layer3/typed/CursorToIndexPoint.java
@@ -32,6 +32,11 @@ public String toString() {
public void beforeFirst() {
indCol.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ indCol.afterLast();
+ }
@Override
public Holder<IndexPoint> nextImpl() {
@@ -44,4 +49,14 @@ public void beforeFirst() {
return new Holder<IndexPoint>(p);
}
+ @Override
+ public Holder<IndexPoint> previousImpl() {
+ Holder<IndexColumn> previous = indCol.previousImpl();
+ if(previous == null)
+ return null;
+
+ IndexColumn col = previous.getValue();
+ IndexPoint p = new IndexPoint(idMeta, col, valueMeta);
+ return new Holder<IndexPoint>(p);
+ }
}
View
10 input/javasrc/com/alvazan/orm/layer3/typed/CursorTypedResp.java
@@ -43,6 +43,11 @@ public void beforeFirst() {
if(keysIterable != null)
keys = keysIterable.iterator();
}
+
+ @Override
+ public void afterLast() {
+ throw new UnsupportedOperationException("Reverse iteration is not yet supported for this curor type. Try sending in your keys in reverse order");
+ }
@Override
public Holder<KeyValue<TypedRow>> nextImpl() {
@@ -54,6 +59,11 @@ public void beforeFirst() {
return new Holder<KeyValue<TypedRow>>(val);
}
+ @Override
+ public Holder<KeyValue<TypedRow>> previousImpl() {
+ throw new UnsupportedOperationException("Reverse iteration is not yet supported for this curor type. Try sending in your keys in reverse order");
+ }
+
private KeyValue<TypedRow> nextChunk(KeyValue<Row> keyValue) {
if(query == null) {
return nextVal(keyValue);
View
77 input/javasrc/com/alvazan/orm/layer3/typed/IndiceCursorProxy.java
@@ -0,0 +1,77 @@
+package com.alvazan.orm.layer3.typed;
+
+import com.alvazan.orm.api.z5api.IndexColumnInfo;
+import com.alvazan.orm.api.z5api.IndexColumnInfo.Wrapper;
+import com.alvazan.orm.api.z8spi.action.IndexColumn;
+import com.alvazan.orm.api.z8spi.conv.Precondition;
+import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
+import com.alvazan.orm.api.z8spi.iter.StringLocal;
+import com.alvazan.orm.api.z8spi.meta.ViewInfo;
+
+public class IndiceCursorProxy implements DirectCursor<byte[]> {
+
+ private DirectCursor<IndexColumnInfo> cursor;
+ private ViewInfo view;
+
+ public IndiceCursorProxy(ViewInfo view, DirectCursor<IndexColumnInfo> indice) {
+ Precondition.check(view, "view");
+ Precondition.check(indice, "indice");
+ this.cursor = indice;
+ this.view = view;
+ }
+
+ @Override
+ public String toString() {
+ String tabs = StringLocal.getAndAdd();
+ String retVal = "IndiceCursorProxy(proxyQueryCursorWithIterable)["
+ +tabs+cursor
+ +tabs+view
+ +tabs+"]";
+ StringLocal.set(tabs.length());
+ return retVal;
+ }
+
+
+ @Override
+ public Holder<byte[]> nextImpl() {
+ Holder<IndexColumnInfo> next = cursor.nextImpl();
+ if(next == null)
+ return null;
+ IndexColumnInfo info = next.getValue();
+ Wrapper wrapper = info.getIndexNode(view);
+ IndexColumn indNode = wrapper.getCol();
+ byte[] key = indNode.getPrimaryKey();
+ if(key == null)
+ throw new IllegalArgumentException("key was null, index data seems corrupt on view="+view+" col="
+ +wrapper.getColMeta()+" some value is tied to a null primary key. Should" +
+ " never happen even in face of eventual consistent, should never happen");
+ return new Holder<byte[]>(key);
+ }
+
+ @Override
+ public Holder<byte[]> previousImpl() {
+ Holder<IndexColumnInfo> prev = cursor.previousImpl();
+ if(prev == null)
+ return null;
+ IndexColumnInfo info = prev.getValue();
+ Wrapper wrapper = info.getIndexNode(view);
+ IndexColumn indNode = wrapper.getCol();
+ byte[] key = indNode.getPrimaryKey();
+ if(key == null)
+ throw new IllegalArgumentException("key was null, index data seems corrupt on view="+view+" col="
+ +wrapper.getColMeta()+" some value is tied to a null primary key. Should" +
+ " never happen even in face of eventual consistent, should never happen");
+ return new Holder<byte[]>(key);
+ }
+
+ @Override
+ public void beforeFirst() {
+ cursor.beforeFirst();
+ }
+
+ @Override
+ public void afterLast() {
+ cursor.afterLast();
+ }
+}
View
11 input/javasrc/com/alvazan/orm/layer3/typed/NoSqlTypedSessionImpl.java
@@ -25,7 +25,8 @@
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.Cursor;
import com.alvazan.orm.api.z8spi.iter.DirectCursor;
-import com.alvazan.orm.api.z8spi.iter.IterToVirtual;
+import com.alvazan.orm.api.z8spi.iter.IndiceToVirtual;
+import com.alvazan.orm.api.z8spi.iter.IterableWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnIdMeta;
import com.alvazan.orm.api.z8spi.meta.DboColumnMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
@@ -162,13 +163,13 @@ public TypedRow find(String cf, Object id) {
if(meta == null)
throw new IllegalArgumentException("Meta for columnfamily="+colFamily+" was not found");
DboColumnMeta idMeta = meta.getIdColumnMeta();
- Iterable<byte[]> noSqlKeys = new IterableTypedProxy<Object>(idMeta, keys);
+ DirectCursor<byte[]> noSqlKeys = new TypedProxyWrappingCursor<Object>(idMeta, new IterableWrappingCursor<Object>(keys));
return findAllImpl2(meta, keys, noSqlKeys, null, batchSize);
}
- <T> AbstractCursor<KeyValue<TypedRow>> findAllImpl2(DboTableMeta meta, Iterable<T> keys, Iterable<byte[]> noSqlKeys, String query, int batchSize) {
-
- Iterable<byte[]> virtKeys = new IterToVirtual(meta, noSqlKeys);
+ <T> AbstractCursor<KeyValue<TypedRow>> findAllImpl2(DboTableMeta meta, Iterable<T> keys, DirectCursor<byte[]> noSqlKeys, String query, int batchSize) {
+
+ DirectCursor<byte[]> virtKeys = new IndiceToVirtual(meta, noSqlKeys);
//NOTE: It is WAY more efficient to find ALL keys at once then it is to
//find one at a time. You would rather have 1 find than 1000 if network latency was 1 ms ;).
AbstractCursor<KeyValue<Row>> rows2 = session.find(meta, virtKeys, true, false, batchSize);
View
5 input/javasrc/com/alvazan/orm/layer3/typed/QueryResultImpl.java
@@ -50,10 +50,11 @@ public QueryResultImpl(SpiMetaQuery metaQuery2,
public Cursor<KeyValue<TypedRow>> getPrimaryViewCursor() {
directCursor.beforeFirst();
ViewInfo mainView = metaQuery.getTargetViews().get(0);
- Iterable<byte[]> indexIterable = new IterableCursorProxy(mainView, directCursor);
+ IndiceCursorProxy indiceCursor = new IndiceCursorProxy(mainView, directCursor);
DboTableMeta meta = mainView.getTableMeta();
- Cursor<KeyValue<TypedRow>> results = session.findAllImpl2(meta, null, indexIterable, metaQuery.getQuery(), batchSize);
+
+ Cursor<KeyValue<TypedRow>> results = session.findAllImpl2(meta, null, indiceCursor, metaQuery.getQuery(), batchSize);
return results;
}
View
50 input/javasrc/com/alvazan/orm/layer3/typed/TypedProxyWrappingCursor.java
@@ -0,0 +1,50 @@
+package com.alvazan.orm.layer3.typed;
+
+import com.alvazan.orm.api.z8spi.conv.Precondition;
+import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
+import com.alvazan.orm.api.z8spi.meta.DboColumnMeta;
+
+public class TypedProxyWrappingCursor<T> implements DirectCursor<byte[]> {
+
+ private DboColumnMeta idMeta;
+ private DirectCursor<T> keys;
+
+ public TypedProxyWrappingCursor(DboColumnMeta idMeta, DirectCursor<T> keys2) {
+ Precondition.check(keys2, "keys");
+ this.idMeta = idMeta;
+ this.keys = keys2;
+ }
+
+
+ @Override
+ public Holder<byte[]> nextImpl() {
+ Holder<T> nextKey = keys.nextImpl();
+ if (nextKey == null)
+ return null;
+ T k = nextKey.getValue();
+ byte[] rowK = idMeta.convertToStorage2(k);
+ return new Holder<byte[]>(rowK);
+ }
+
+ @Override
+ public Holder<byte[]> previousImpl() {
+ Holder<T> nextKey = keys.previousImpl();
+ if (nextKey == null)
+ return null;
+ T k = nextKey.getValue();
+ byte[] rowK = idMeta.convertToStorage2(k);
+ return new Holder<byte[]>(rowK);
+ }
+
+ @Override
+ public void beforeFirst() {
+ keys.beforeFirst();
+ }
+
+ @Override
+ public void afterLast() {
+ keys.afterLast();
+ }
+
+}
View
3  input/javasrc/com/alvazan/orm/layer5/nosql/cache/NoSqlReadCacheImpl.java
@@ -26,6 +26,7 @@
import com.alvazan.orm.api.z8spi.action.IndexColumn;
import com.alvazan.orm.api.z8spi.conv.ByteArray;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
public class NoSqlReadCacheImpl implements NoSqlSession, Cache {
@@ -100,7 +101,7 @@ public Row find(DboTableMeta colFamily, byte[] rowKey) {
@Override
public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily,
- Iterable<byte[]> rowKeys, boolean skipCache, boolean cacheResults, Integer batchSize) {
+ DirectCursor<byte[]> rowKeys, boolean skipCache, boolean cacheResults, Integer batchSize) {
Cache c = new EmptyCache(this, skipCache, cacheResults);
//NOTE: I would put a finally to clear out the threadlocal normally BUT sometimes log statements may
View
6 input/javasrc/com/alvazan/orm/layer5/nosql/cache/NoSqlWriteCacheImpl.java
@@ -25,7 +25,9 @@
import com.alvazan.orm.api.z8spi.action.RemoveIndex;
import com.alvazan.orm.api.z8spi.conv.StandardConverters;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
+import com.alvazan.orm.api.z8spi.iter.IterableWrappingCursor;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
public class NoSqlWriteCacheImpl implements NoSqlSession {
@@ -100,7 +102,7 @@ public void removeFromIndex(DboTableMeta cf, String indexColFamily, byte[] rowKe
@Override
public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily,
- Iterable<byte[]> rowKeys, boolean skipCache, boolean cacheResults, Integer batchSize) {
+ DirectCursor<byte[]> rowKeys, boolean skipCache, boolean cacheResults, Integer batchSize) {
int size = 500;
if(batchSize != null)
size = batchSize;
@@ -108,7 +110,7 @@ public void removeFromIndex(DboTableMeta cf, String indexColFamily, byte[] rowKe
}
private List<Row> find(DboTableMeta colFamily, List<byte[]> keys, boolean cacheResults) {
- AbstractCursor<KeyValue<Row>> results = find(colFamily, keys, false, cacheResults, null);
+ AbstractCursor<KeyValue<Row>> results = find(colFamily, new IterableWrappingCursor<byte[]>(keys), false, cacheResults, null);
List<Row> rows = new ArrayList<Row>();
while(true) {
Holder<KeyValue<Row>> holder = results.nextImpl();
View
43 input/javasrc/com/alvazan/orm/layer5/query/CachingCursor.java
@@ -1,8 +1,8 @@
package com.alvazan.orm.layer5.query;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import com.alvazan.orm.api.z5api.IndexColumnInfo;
import com.alvazan.orm.api.z8spi.conv.Precondition;
@@ -21,7 +21,7 @@
private DirectCursor<IndexColumnInfo> cursor;
private List<IndexColumnInfo> cached = new ArrayList<IndexColumnInfo>();
- private Iterator<IndexColumnInfo> cachedIter;
+ private ListIterator<IndexColumnInfo> cachedIter;
private boolean cacheEnabled = false;
public CachingCursor(DirectCursor<IndexColumnInfo> cursor) {
@@ -54,6 +54,24 @@ public String toString() {
}
return null;
}
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ if(cacheEnabled) {
+ return fetchPreviousFromCache();
+ }
+ Holder<IndexColumnInfo> previous = cursor.previousImpl();
+ if(previous != null) {
+ if(cached.size() < 500)
+ cached.add(0, previous.getValue());
+ return previous;
+ }
+
+ if(cached.size() < 500) {
+ cacheEnabled = true;
+ }
+ return null;
+ }
private Holder<IndexColumnInfo> fetchFromCache() {
if(cachedIter == null)
@@ -63,12 +81,31 @@ else if(!cachedIter.hasNext())
IndexColumnInfo next = cachedIter.next();
return new Holder<IndexColumnInfo>(next.copy());
}
+
+ private Holder<IndexColumnInfo> fetchPreviousFromCache() {
+ if(cachedIter == null)
+ return null;
+ else if(!cachedIter.hasPrevious())
+ return null;
+ IndexColumnInfo prev = cachedIter.previous();
+ return new Holder<IndexColumnInfo>(prev.copy());
+ }
@Override
public void beforeFirst() {
if(cacheEnabled)
- cachedIter = cached.iterator();
+ cachedIter = cached.listIterator();
else
cursor.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ if(cacheEnabled) {
+ cachedIter = cached.listIterator();
+ while(cachedIter.hasNext()) cachedIter.next();
+ }
+ else
+ cursor.afterLast();
+ }
}
View
82 input/javasrc/com/alvazan/orm/layer5/query/CursorForAnd.java
@@ -70,6 +70,36 @@ public String toString() {
}
return null;
}
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ while(true) {
+ Holder<IndexColumnInfo> prevFromCursor = leftResults.previousImpl();
+ if(prevFromCursor == null)
+ break;
+ IndexColumnInfo next = prevFromCursor.getValue();
+
+ if(cachedMap != null) {
+ Holder<IndexColumnInfo> result = quickHashLookup(next);
+ if(result != null)
+ return result;
+ } else if(!ranFullInnerLoopTo500Once) {
+ rightResults.afterLast();
+ Holder<IndexColumnInfo> result = runFullInnerLoopOnceBackward(next);
+ if(result != null)
+ return result;
+ } else {
+ //Need to change to lookahead joining here as well as switch join types on the fly
+ //This stinks as we have to re-read from the database every 1000 rows!!!! We should find out if
+ //we can do any kind of counting or something so we don't have to go back to database every time
+ rightResults.afterLast();
+ Holder<IndexColumnInfo> result = runInnerLoopBackward(next);
+ if(result != null)
+ return result;
+ }
+ }
+ return null;
+ }
private Holder<IndexColumnInfo> runFullInnerLoopOnce(IndexColumnInfo next) {
Map<ByteArray, IndexColumnInfo> pkToRightSide = new HashMap<ByteArray, IndexColumnInfo>();
@@ -98,6 +128,35 @@ public String toString() {
cachedMap = pkToRightSide;
return matchedResult;
}
+
+ private Holder<IndexColumnInfo> runFullInnerLoopOnceBackward(IndexColumnInfo previous) {
+ Map<ByteArray, IndexColumnInfo> pkToRightSide = new HashMap<ByteArray, IndexColumnInfo>();
+ Holder<IndexColumnInfo> matchedResult = null;
+ while(true) {
+ Holder<IndexColumnInfo> previousFromCursor = rightResults.previousImpl();
+ if(previousFromCursor == null)
+ break;
+ IndexColumnInfo andedInfo = previousFromCursor.getValue();
+ ByteArray key1 = previous.getPrimaryKey(leftView);
+ ByteArray key2 = andedInfo.getPrimaryKey(rightView);
+ if(pkToRightSide.size() < 500)
+ pkToRightSide.put(key2, andedInfo);
+ if(matchedResult == null && key1.equals(key2)) {
+ previous.mergeResults(andedInfo);
+ matchedResult = new Holder<IndexColumnInfo>(previous);
+ }
+
+ if(matchedResult != null && pkToRightSide.size()>=500) {
+ //we have exceeded cache size so we can't switch to a Hash join :(
+ return matchedResult;
+ }
+ }
+
+ if(pkToRightSide.size() < 500)
+ cachedMap = pkToRightSide;
+ return matchedResult;
+ }
+
private Holder<IndexColumnInfo> quickHashLookup(IndexColumnInfo next) {
ByteArray key1 = next.getPrimaryKey(leftView);
@@ -124,6 +183,23 @@ public String toString() {
return null;
}
+
+ private Holder<IndexColumnInfo> runInnerLoopBackward(IndexColumnInfo previous) {
+ while(true) {
+ Holder<IndexColumnInfo> prevFromCursor = rightResults.previousImpl();
+ if(prevFromCursor == null)
+ break;
+ IndexColumnInfo andedInfo = prevFromCursor.getValue();
+ ByteArray key1 = previous.getPrimaryKey(leftView);
+ ByteArray key2 = andedInfo.getPrimaryKey(rightView);
+ if(key1.equals(key2)) {
+ previous.mergeResults(andedInfo);
+ return new Holder<IndexColumnInfo>(previous);
+ }
+ }
+
+ return null;
+ }
@Override
@@ -131,5 +207,11 @@ public void beforeFirst() {
leftResults.beforeFirst();
rightResults.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ leftResults.afterLast();
+ rightResults.afterLast();
+ }
}
View
70 input/javasrc/com/alvazan/orm/layer5/query/CursorForJoin.java
@@ -1,8 +1,8 @@
package com.alvazan.orm.layer5.query;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import com.alvazan.orm.api.z5api.IndexColumnInfo;
import com.alvazan.orm.api.z5api.NoSqlSession;
@@ -26,7 +26,7 @@
private DirectCursor<IndexColumn> cachedFromNewView;
private ViewInfo newView;
private ViewInfo rightView;
- private Iterator<IndexColumnInfo> cachedFromRightResults;
+ private ListIterator<IndexColumnInfo> cachedFromRightResults;
private IndexColumnInfo lastCachedRightSide;
private DboColumnMeta colMeta;
@@ -72,6 +72,13 @@ public void beforeFirst() {
this.rightResults.beforeFirst();
cachedFromNewView = null;
}
+
+ @Override
+ public void afterLast() {
+ this.rightResults.afterLast();
+ cachedFromNewView = null;
+ }
+
@Override
public Holder<IndexColumnInfo> nextImpl() {
@@ -85,6 +92,19 @@ public void beforeFirst() {
return fetchAnother();
}
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ if(cachedFromNewView != null) {
+ Holder<IndexColumn> prev = cachedFromNewView.previousImpl();
+ if(prev != null) {
+ return createResult(prev);
+ }
+ //we need to fetch more...
+ }
+
+ return fetchAnotherPrevious();
+ }
private Holder<IndexColumnInfo> fetchAnother() {
//HERE we want to batch for performance
@@ -94,7 +114,7 @@ public void beforeFirst() {
//optimize by fetching LOTS of keys at one time up to batchSize
buildValuesToFind(values, rightListResults);
- cachedFromRightResults = rightListResults.iterator();
+ cachedFromRightResults = rightListResults.listIterator();
cachedFromNewView = session.scanIndex(scanInfo, values);
Holder<IndexColumn> next = cachedFromNewView.nextImpl();
@@ -126,6 +146,50 @@ private void buildValuesToFind(List<byte[]> values,
}
}
+
+
+ private Holder<IndexColumnInfo> fetchAnotherPrevious() {
+ //HERE we want to batch for performance
+ List<byte[]> values = new ArrayList<byte[]>();
+ List<IndexColumnInfo> rightListResults = new ArrayList<IndexColumnInfo>();
+
+ //optimize by fetching LOTS of keys at one time up to batchSize
+ buildPreviousValuesToFind(values, rightListResults);
+
+ cachedFromRightResults = rightListResults.listIterator();
+ while(cachedFromRightResults.hasNext())cachedFromRightResults.next();
+ cachedFromNewView = session.scanIndex(scanInfo, values);
+ cachedFromNewView.afterLast();
+ Holder<IndexColumn> next = cachedFromNewView.previousImpl();
+
+ if(next == null)
+ return null;
+ else if(lastCachedRightSide == null)
+ lastCachedRightSide = cachedFromRightResults.previous();
+
+ return createResult(next);
+ }
+
+ private void buildPreviousValuesToFind(List<byte[]> values,
+ List<IndexColumnInfo> rightListResults) {
+ //boolean rightResultsExhausted = false;
+ int counter = 0;
+ while(true) {
+ Holder<IndexColumnInfo> rightHolder = rightResults.previousImpl();
+ if(rightHolder == null) {
+ // rightResultsExhausted = true;
+ break;
+ } else if(batchSize != null && batchSize.intValue() < counter)
+ break;
+
+ IndexColumnInfo rightResult = rightHolder.getValue();
+ ByteArray pk = rightResult.getPrimaryKey(rightView);
+ values.add(pk.getKey());
+ rightListResults.add(rightResult);
+ counter++;
+ }
+
+ }
private Holder<IndexColumnInfo> createResult(
com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<IndexColumn> next) {
View
89 input/javasrc/com/alvazan/orm/layer5/query/CursorForOr.java
@@ -1,10 +1,6 @@
package com.alvazan.orm.layer5.query;
-import java.util.HashMap;
-import java.util.Map;
-
import com.alvazan.orm.api.z5api.IndexColumnInfo;
-import com.alvazan.orm.api.z8spi.conv.ByteArray;
import com.alvazan.orm.api.z8spi.conv.Precondition;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
import com.alvazan.orm.api.z8spi.iter.DirectCursor;
@@ -14,9 +10,10 @@
private DirectCursor<IndexColumnInfo> leftResults;
private DirectCursor<IndexColumnInfo> rightResults;
- private Map<ByteArray, IndexColumnInfo> pksToAlreadyFound = new HashMap<ByteArray, IndexColumnInfo>();
private ViewInfo leftView;
private ViewInfo rightView;
+ private Holder<IndexColumnInfo> currLeftVal;
+ private Holder<IndexColumnInfo> currRightVal;
public CursorForOr(ViewInfo leftView, DirectCursor<IndexColumnInfo> leftResults2,
ViewInfo rightView, DirectCursor<IndexColumnInfo> rightResults2) {
@@ -28,43 +25,73 @@ public CursorForOr(ViewInfo leftView, DirectCursor<IndexColumnInfo> leftResults2
this.rightView = rightView;
this.leftResults = leftResults2;
this.rightResults = rightResults2;
+ beforeFirst();
}
@Override
public void beforeFirst() {
leftResults.beforeFirst();
rightResults.beforeFirst();
- pksToAlreadyFound.clear();
+ currLeftVal = leftResults.nextImpl();
+ currRightVal = rightResults.nextImpl();
+ }
+
+ @Override
+ public void afterLast() {
+ leftResults.afterLast();
+ rightResults.afterLast();
+ currLeftVal = leftResults.previousImpl();
+ currRightVal = rightResults.previousImpl();
}
@Override
public Holder<IndexColumnInfo> nextImpl() {
- while(true) {
- Holder<IndexColumnInfo> nextFromLeftCursor = leftResults.nextImpl();
- if(nextFromLeftCursor == null)
- break;
- IndexColumnInfo leftResult = nextFromLeftCursor.getValue();
- ByteArray pk = leftResult.getPrimaryKey(leftView);
- pksToAlreadyFound.put(pk, leftResult);
- return new Holder<IndexColumnInfo>(leftResult);
- }
-
- //NOW, as we go through the results on the right side, make sure we filter out
- //duplicate primary keys by checking ones that we already returned.
- while(true) {
- Holder<IndexColumnInfo> fromRightCursor = rightResults.nextImpl();
- if(fromRightCursor == null)
- break;
- IndexColumnInfo rightResult = fromRightCursor.getValue();
- IndexColumnInfo found = pksToAlreadyFound.get(rightResult.getPrimaryKey(rightView));
- if(found != null) {
- found.mergeResults(rightResult);
- } else {
- return new Holder<IndexColumnInfo>(rightResult);
+ return nextImpl(false);
+ }
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ return nextImpl(true);
+ }
+
+ private Holder<IndexColumnInfo> nextImpl(boolean reverse) {
+ if (currLeftVal != null && currRightVal != null) {
+ int compareResult = currLeftVal.getValue().getPrimaryKey(leftView).compareTo(currRightVal.getValue().getPrimaryKey(rightView));
+ if (reverse)
+ compareResult = compareResult*-1;
+ if (compareResult < 0)
+ return useLeft(reverse);
+ else if (compareResult > 0)
+ return useRight(reverse);
+ else { // they are the same, use either, and skip the unused one since it's identical
+ useRight(reverse);
+ return useLeft(reverse);
}
}
-
- return null;
+ else {
+ if (currLeftVal!=null)
+ return useLeft(reverse);
+ else if (currRightVal!=null)
+ return useRight(reverse);
+ else return null;
+ }
+ }
+
+ private Holder<IndexColumnInfo> useLeft(boolean reverse) {
+ Holder<IndexColumnInfo> retVal = currLeftVal;
+ if (reverse)
+ currLeftVal = leftResults.previousImpl();
+ else
+ currLeftVal = leftResults.nextImpl();
+ return retVal;
+ }
+
+ private Holder<IndexColumnInfo> useRight(boolean reverse) {
+ Holder<IndexColumnInfo> retVal = currRightVal;
+ if (reverse)
+ currRightVal = rightResults.previousImpl();
+ else
+ currRightVal = rightResults.nextImpl();
+ return retVal;
}
-
}
View
32 input/javasrc/com/alvazan/orm/layer5/query/CursorForPrimaryKey.java
@@ -41,19 +41,41 @@ public String toString() {
public void beforeFirst() {
cursor.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ cursor.beforeFirst();
+ }
@Override
public Holder<IndexColumnInfo> nextImpl() {
Holder<KeyValue<Row>> holder = cursor.nextImpl();
+ return buildHolder(holder);
+ }
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ Holder<KeyValue<Row>> holder = cursor.previousImpl();
+ return buildHolder(holder);
+ }
+
+ private Holder<IndexColumnInfo> buildHolder(Holder<KeyValue<Row>> holder) {
if(holder == null)
return null;
KeyValue<Row> pkCol = holder.getValue();
- if(pkCol == null || pkCol.getValue() == null)
- return null;
+ if(pkCol == null)
+ return new Holder<IndexColumnInfo>(null);
IndexColumn c = new IndexColumn();
- c.setPrimaryKey(colMeta.getOwner().getIdColumnMeta().unformVirtRowKey(pkCol.getValue().getKey()));
- c.setIndexedValue(colMeta.getOwner().getIdColumnMeta().unformVirtRowKey(pkCol.getValue().getKey()));
- c.setValue(pkCol.getValue().getKey());
+ byte[] pk = null;
+ if (pkCol.getValue() == null)
+ return new Holder<IndexColumnInfo>(null);
+ else
+ pk = pkCol.getValue().getKey();
+ if (pk != null) {
+ c.setPrimaryKey(colMeta.getOwner().getIdColumnMeta().unformVirtRowKey(pk));
+ c.setIndexedValue(colMeta.getOwner().getIdColumnMeta().unformVirtRowKey(pk));
+ c.setValue(pk);
+ }
IndexColumnInfo info = new IndexColumnInfo();
info.putIndexNode(viewInfo, c, colMeta);
return new Holder<IndexColumnInfo>(info);
View
18 input/javasrc/com/alvazan/orm/layer5/query/CursorSimpleTranslator.java
@@ -36,6 +36,11 @@ public String toString() {
public void beforeFirst() {
cursor.beforeFirst();
}
+
+ @Override
+ public void afterLast() {
+ cursor.afterLast();
+ }
@Override
public Holder<IndexColumnInfo> nextImpl() {
@@ -49,5 +54,18 @@ public void beforeFirst() {
info.putIndexNode(viewInfo, indCol, colMeta);
return new Holder<IndexColumnInfo>(info);
}
+
+ @Override
+ public Holder<IndexColumnInfo> previousImpl() {
+ Holder<IndexColumn> holder = cursor.previousImpl();
+ if(holder == null)
+ return null;
+ IndexColumn indCol = holder.getValue();
+ if(indCol == null)
+ return new Holder<IndexColumnInfo>(null);
+ IndexColumnInfo info = new IndexColumnInfo();
+ info.putIndexNode(viewInfo, indCol, colMeta);
+ return new Holder<IndexColumnInfo>(info);
+ }
}
View
31 input/javasrc/com/alvazan/orm/layer5/query/SpiIndexQueryImpl.java
@@ -25,6 +25,7 @@
import com.alvazan.orm.api.z8spi.conv.StandardConverters;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.DirectCursor;
+import com.alvazan.orm.api.z8spi.iter.IterableWrappingCursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.api.z8spi.meta.ViewInfo;
@@ -34,6 +35,7 @@
import com.alvazan.orm.parser.antlr.JoinMeta;
import com.alvazan.orm.parser.antlr.JoinType;
import com.alvazan.orm.parser.antlr.NoSqlLexer;
+import com.alvazan.orm.parser.antlr.ParsedNode;
import com.alvazan.orm.parser.antlr.PartitionMeta;
import com.alvazan.orm.parser.antlr.StateAttribute;
import com.alvazan.orm.parser.antlr.ViewInfoImpl;
@@ -117,6 +119,7 @@ private ScanInfo createScanInfo(ViewInfoImpl tableInfo, DboColumnMeta metaCol) {
case NoSqlLexer.GE:
case NoSqlLexer.LE:
case NoSqlLexer.BETWEEN:
+ case NoSqlLexer.IN:
return processRangeExpression(parent, alreadyJoinedViews);
default:
throw new UnsupportedOperationException("bug, unsupported type="+type);
@@ -172,6 +175,9 @@ private ScanInfo createScanInfo(ViewInfoImpl tableInfo, DboColumnMeta metaCol) {
if(root.getType() == NoSqlLexer.BETWEEN) {
ExpressionNode grandChild = root.getChild(ChildSide.LEFT).getChild(ChildSide.LEFT);
attr = (StateAttribute) grandChild.getState();
+ } else if (root.getType() == NoSqlLexer.IN) {
+ ExpressionNode grandChild = root.getChild(ChildSide.LEFT);
+ attr = (StateAttribute) grandChild.getState();
} else {
attr = (StateAttribute) root.getChild(ChildSide.LEFT).getState();
}
@@ -201,10 +207,10 @@ private ScanInfo createScanInfo(ViewInfoImpl tableInfo, DboColumnMeta metaCol) {
|| root.getType() == NoSqlLexer.GE
|| root.getType() == NoSqlLexer.LT
|| root.getType() == NoSqlLexer.LE
- || root.isInBetweenExpression()) {
+ || root.isBetweenExpression()) {
Key from = null;
Key to = null;
- if(root.isInBetweenExpression()) {
+ if(root.isBetweenExpression()) {
ExpressionNode node = root.getGreaterThan();
ExpressionNode node2 = root.getLessThan();
from = createLeftKey(node, info);
@@ -217,12 +223,22 @@ private ScanInfo createScanInfo(ViewInfoImpl tableInfo, DboColumnMeta metaCol) {
} else
throw new UnsupportedOperationException("not done yet here");
scan = session.scanIndex(scanInfo, from, to, batchSize);
+ } else if(root.getType() == NoSqlLexer.IN) {
+ List<byte[]> values = new ArrayList<byte[]>();
+ List<ParsedNode> keys = root.getChildrenForIn();
+ for (ParsedNode keyNode : keys) {
+ byte[] data = retrieveValue(info, (ExpressionNode) keyNode);
+ byte[] virtualkey = info.getOwner().getIdColumnMeta().formVirtRowKey(data);
+ values.add(virtualkey);
+ }
+ scan = session.scanIndex(scanInfo, values);
} else
throw new UnsupportedOperationException("not supported yet. type="+root.getType());
DirectCursor<IndexColumnInfo> processKeys = processKeys(viewInfo, info, scan);
return processKeys;
}
+ @SuppressWarnings("unchecked")
private DirectCursor<IndexColumnInfo> processPrimaryKey(ExpressionNode root, ScanInfo scanInfo, ViewInfoImpl viewInfo, DboColumnMeta info) {
AbstractCursor<KeyValue<Row>> scan;
if(root.getType() == NoSqlLexer.EQ) {
@@ -232,7 +248,16 @@ private ScanInfo createScanInfo(ViewInfoImpl tableInfo, DboColumnMeta metaCol) {
byte[] virtualkey = info.getOwner().getIdColumnMeta().formVirtRowKey(data);
List<byte[]> keyList= new ArrayList<byte[]>();
keyList.add(virtualkey);
- scan = session.find(info.getOwner(), keyList, false, true, batchSize);
+ scan = session.find(info.getOwner(), new IterableWrappingCursor<byte[]>(keyList), false, true, batchSize);
+ } else if (root.getType() == NoSqlLexer.IN) {
+ List<byte[]> keyList = new ArrayList<byte[]>();
+ List<ParsedNode> keys = root.getChildrenForIn();
+ for (ParsedNode keyNode : keys) {
+ byte[] data = retrieveValue(info, (ExpressionNode) keyNode);
+ byte[] virtualkey = info.getOwner().getIdColumnMeta().formVirtRowKey(data);
+ keyList.add(virtualkey);
+ }
+ scan = session.find(info.getOwner(), new IterableWrappingCursor<byte[]>(keyList), false, true, batchSize);
} else
throw new UnsupportedOperationException("Other operations not supported yet for Primary Key. Use @NoSQLIndexed for Primary Key.type="+root.getType());
DirectCursor<IndexColumnInfo> processKeys = processKeysforPK(viewInfo, info, scan);
View
39 input/javasrc/com/alvazan/orm/layer9z/spi/db/cassandra/CassandraSession.java
@@ -27,6 +27,7 @@
import com.alvazan.orm.api.z8spi.action.RemoveColumn;
import com.alvazan.orm.api.z8spi.action.RemoveIndex;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
+import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.iter.EmptyCursor;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.netflix.astyanax.Cluster;
@@ -71,7 +72,7 @@ public void close() {
@Override
public AbstractCursor<KeyValue<Row>> find(DboTableMeta colFamily,
- Iterable<byte[]> rowKeys, Cache cache, int batchSize, BatchListener list, MetaLookup mgr) {
+ DirectCursor<byte[]> rowKeys, Cache cache, int batchSize, BatchListener list, MetaLookup mgr) {
Info info = columnFamilies.fetchColumnFamilyInfo(colFamily.getColumnFamily(), mgr);
if(info == null) {
//If there is no column family in cassandra, then we need to return no rows to the user...
@@ -294,6 +295,17 @@ public void clearImpl() throws ConnectionException {
ByteBufferRange range = rangeBldr.build();
return createBasicRowQuery(rowKey, info1, range);
}
+
+ @Override
+ public RowQuery<byte[], byte[]> createRowQueryReverse() {
+ RangeBuilder rangeBldr = new RangeBuilder().setStart(to).setEnd(from).setReversed(true);
+ if(batchSize != null)
+ rangeBldr = rangeBldr.setLimit(batchSize);
+ ByteBufferRange range = rangeBldr.build();
+ return createBasicRowQuery(rowKey, info1, range);
+ }
+
+
};
@@ -302,6 +314,10 @@ public void clearImpl() throws ConnectionException {
@Override
public AbstractCursor<IndexColumn> scanIndex(ScanInfo info, List<byte[]> values, BatchListener batchList, MetaLookup mgr) {
+ return scanIndex(info, values, batchList, mgr, false);
+ }
+
+ public AbstractCursor<IndexColumn> scanIndex(ScanInfo info, List<byte[]> values, BatchListener batchList, MetaLookup mgr, boolean reverse) {
String colFamily = info.getIndexColFamily();
Info info1 = columnFamilies.fetchColumnFamilyInfo(colFamily, mgr);
if(info1 == null) {
@@ -314,7 +330,7 @@ public void clearImpl() throws ConnectionException {
if(type == ColumnType.COMPOSITE_INTEGERPREFIX ||
type == ColumnType.COMPOSITE_DECIMALPREFIX ||
type == ColumnType.COMPOSITE_STRINGPREFIX) {
- StartQueryListener listener = new StartQueryManyKeys(columnFamilies, info1, info, values);
+ StartQueryListener listener = new StartQueryManyKeys(columnFamilies, info1, info, values, reverse);
return new CursorOfFutures(listener, batchList);
} else
throw new UnsupportedOperationException("not done here yet");
@@ -344,7 +360,7 @@ public void clearImpl() throws ConnectionException {
throw new UnsupportedOperationException("not done here yet");
}
- public static CompositeRangeBuilder setupRangeBuilder(Key from, Key to, Info info1) {
+ public static CompositeRangeBuilder setupRangeBuilder(Key from, Key to, Info info1, boolean reverse) {
AnnotatedCompositeSerializer serializer = info1.getCompositeSerializer();
CompositeRangeBuilder range = serializer.buildRange();
if(from != null) {
@@ -359,6 +375,8 @@ public static CompositeRangeBuilder setupRangeBuilder(Key from, Key to, Info inf
else
range = range.lessThan(to.getKey());
}
+ if (reverse)
+ range = range.reverse();
return range;
}
@@ -381,6 +399,7 @@ private RowQuery createBasicRowQuery(byte[] rowKey, Info info1, ByteBufferRange
public interface CreateColumnSliceCallback {
RowQuery<byte[], byte[]> createRowQuery();
+ RowQuery<byte[], byte[]> createRowQueryReverse();
}