33import com .google .common .base .Preconditions ;
44import com .google .common .collect .Iterables ;
55import com .google .common .collect .Sets ;
6+ import tech .ydb .yoj .DeprecationWarnings ;
67import tech .ydb .yoj .databind .expression .FilterExpression ;
78import tech .ydb .yoj .databind .expression .OrderExpression ;
89import tech .ydb .yoj .databind .schema .ObjectSchema ;
1415import tech .ydb .yoj .repository .db .Range ;
1516import tech .ydb .yoj .repository .db .Table ;
1617import tech .ydb .yoj .repository .db .TableDescriptor ;
18+ import tech .ydb .yoj .repository .db .TableQueryBuilder ;
1719import tech .ydb .yoj .repository .db .TableQueryImpl ;
1820import tech .ydb .yoj .repository .db .ViewSchema ;
1921import tech .ydb .yoj .repository .db .cache .FirstLevelCache ;
3234import static java .util .stream .Collectors .toList ;
3335import static java .util .stream .Collectors .toUnmodifiableMap ;
3436import static java .util .stream .Collectors .toUnmodifiableSet ;
37+ import static tech .ydb .yoj .repository .db .TableQueryImpl .getEntityByIdComparator ;
3538
3639public class InMemoryTable <T extends Entity <T >> implements Table <T > {
3740 private final EntitySchema <T > schema ;
3841 private final TableDescriptor <T > tableDescriptor ;
3942 private final InMemoryRepositoryTransaction transaction ;
4043
41- @ Deprecated // Don't use DbMemory, use other constructor instead
44+ /**
45+ * @deprecated {@code DbMemory} and this constructor will be removed in YOJ 3.0.0.
46+ * Please use other constructors instead.
47+ */
48+ @ Deprecated (forRemoval = true )
4249 public InMemoryTable (DbMemory <T > memory ) {
4350 this (memory .transaction (), memory .type ());
51+ DeprecationWarnings .warnOnce ("new InMemoryTable(DbMemory)" ,
52+ "Please do not use the InMemoryTable(DbMemory<T>) constructor, it will be removed in YOJ 3.0.0" );
4453 }
4554
4655 public InMemoryTable (InMemoryRepositoryTransaction transaction , Class <T > type ) {
47- this (transaction , TableDescriptor .from (EntitySchema .of (type )));
56+ this .schema = EntitySchema .of (type );
57+ this .tableDescriptor = TableDescriptor .from (schema );
58+ this .transaction = transaction ;
4859 }
4960
5061 public InMemoryTable (InMemoryRepositoryTransaction transaction , TableDescriptor <T > tableDescriptor ) {
@@ -53,6 +64,11 @@ public InMemoryTable(InMemoryRepositoryTransaction transaction, TableDescriptor<
5364 this .transaction = transaction ;
5465 }
5566
67+ @ Override
68+ public TableQueryBuilder <T > query () {
69+ return new TableQueryBuilder <>(this , schema );
70+ }
71+
5672 @ Override
5773 public List <T > findAll () {
5874 transaction .getWatcher ().markTableRead (tableDescriptor );
@@ -103,7 +119,7 @@ public List<T> find(
103119 @ Nullable Long offset
104120 ) {
105121 // NOTE: InMemoryTable doesn't handle index.
106- return InMemoryQueries .find (() -> findAll ().stream (), filter , orderBy , limit , offset );
122+ return TableQueryImpl .find (() -> findAll ().stream (), schema , filter , orderBy , limit , offset );
107123 }
108124
109125 @ Override
@@ -173,8 +189,8 @@ public TableDescriptor<T> getTableDescriptor() {
173189
174190 @ Override
175191 public T find (Entity .Id <T > id ) {
176- if (id . isPartial ( )) {
177- throw new IllegalArgumentException ("Cannot use partial id in find method" );
192+ if (TableQueryImpl . isPartialId ( id , schema )) {
193+ throw new IllegalArgumentException ("Cannot use partial ID in Table. find() method" );
178194 }
179195 return transaction .getTransactionLocal ().firstLevelCache (tableDescriptor ).get (id , __ -> {
180196 markKeyRead (id );
@@ -185,13 +201,13 @@ public T find(Entity.Id<T> id) {
185201
186202 @ Override
187203 public <ID extends Entity .Id <T >> List <T > find (Set <ID > ids ) {
188- return TableQueryImpl .find (this , getFirstLevelCache (), ids );
204+ return TableQueryImpl .find (this , schema , getFirstLevelCache (), ids );
189205 }
190206
191207 @ Override
192208 public <V extends View > V find (Class <V > viewType , Entity .Id <T > id ) {
193- if (id . isPartial ( )) {
194- throw new IllegalArgumentException ("Cannot use partial id in find method" );
209+ if (TableQueryImpl . isPartialId ( id , schema )) {
210+ throw new IllegalArgumentException ("Cannot use partial ID in Table. find() method" );
195211 }
196212
197213 FirstLevelCache <T > cache = transaction .getTransactionLocal ().firstLevelCache (tableDescriptor );
@@ -208,10 +224,13 @@ public <V extends View> V find(Class<V> viewType, Entity.Id<T> id) {
208224 @ Override
209225 @ SuppressWarnings ("unchecked" )
210226 public <ID extends Entity .Id <T >> List <T > find (Range <ID > range ) {
211- transaction .getWatcher ().markRangeRead (tableDescriptor , range );
227+ Preconditions .checkArgument (range .getType () == schema .getIdSchema (),
228+ "ID schema mismatch: Range was constructed with a different ID schema than the YdbTable" );
229+
230+ markRangeRead (range );
212231 return findAll0 ().stream ()
213232 .filter (e -> range .contains ((ID ) e .getId ()))
214- .sorted (EntityIdSchema . SORT_ENTITY_BY_ID )
233+ .sorted (getEntityByIdComparator ( schema ) )
215234 .collect (toList ());
216235 }
217236
@@ -232,7 +251,7 @@ public <V extends View, ID extends Entity.Id<T>> List<V> find(Class<V> viewType,
232251
233252 @ Override
234253 public <V extends View , ID extends Entity .Id <T >> List <V > find (Class <V > viewType , Set <ID > ids ) {
235- return find (viewType , ids , null , EntityExpressions .defaultOrder (getType () ), null );
254+ return find (viewType , ids , null , EntityExpressions .defaultOrder (schema ), null );
236255 }
237256
238257 @ Override
@@ -404,9 +423,10 @@ private boolean isPrefixedFields(List<String> keyFields, Set<String> fields) {
404423
405424 private <ID extends Entity .Id <T >> void markKeyRead (ID id ) {
406425 EntityIdSchema <Entity .Id <T >> idSchema = schema .getIdSchema ();
407- if (idSchema .flattenFieldNames ().size () != idSchema .flatten (id ).size ()) {
426+ Map <String , Object > eqMap = idSchema .flatten (id );
427+ if (idSchema .flattenFieldNames ().size () != eqMap .size ()) {
408428 // Partial key, will throw error when not searching by PK prefix
409- transaction .getWatcher ().markRangeRead (tableDescriptor , Range .create (id , id ));
429+ transaction .getWatcher ().markRangeRead (tableDescriptor , Range .create (idSchema , eqMap ));
410430 } else {
411431 transaction .getWatcher ().markRowRead (tableDescriptor , id );
412432 }
@@ -475,7 +495,7 @@ public <ID extends Entity.Id<T>> Stream<T> streamPartial(ID partial, int batchSi
475495 Preconditions .checkArgument (1 <= batchSize && batchSize <= 5000 ,
476496 "batchSize must be in range [1, 5000], got %s" , batchSize );
477497
478- Range <ID > range = partial == null ? null : Range . create (partial );
498+ Range <ID > range = rangeForPartialId (partial );
479499 markRangeRead (range );
480500
481501 return streamPartial0 (range );
@@ -508,20 +528,26 @@ public <ID extends Entity.Id<T>> Stream<ID> streamPartialIds(ID partial, int bat
508528 Preconditions .checkArgument (1 <= batchSize && batchSize <= 10000 ,
509529 "batchSize must be in range [1, 10000], got %s" , batchSize );
510530
511- Range <ID > range = partial == null ? null : Range . create (partial );
531+ Range <ID > range = rangeForPartialId (partial );
512532 markRangeRead (range );
513533
514534 return streamPartial0 (range ).map (e -> (ID ) e .getId ());
515535 }
516536
517- private <ID extends Entity .Id <T >> void markRangeRead (Range <ID > range ) {
537+ private <ID extends Entity .Id <T >> void markRangeRead (@ Nullable Range <ID > range ) {
518538 if (range == null ) {
519539 transaction .getWatcher ().markTableRead (tableDescriptor );
520540 } else {
521541 transaction .getWatcher ().markRangeRead (tableDescriptor , range );
522542 }
523543 }
524544
545+ @ Nullable
546+ private <ID extends Entity .Id <T >> Range <ID > rangeForPartialId (ID partial ) {
547+ EntityIdSchema <ID > idSchema = schema .getIdSchema ();
548+ return partial == null ? null : Range .create (idSchema , idSchema .flatten (partial ));
549+ }
550+
525551 private <ID extends Entity .Id <T >> Stream <T > readTableStream (ReadTableParams <ID > params ) {
526552 if (!transaction .getOptions ().getIsolationLevel ().isReadOnly ()) {
527553 throw new IllegalTransactionIsolationLevelException ("readTable" , transaction .getOptions ().getIsolationLevel ());
@@ -533,7 +559,7 @@ private <ID extends Entity.Id<T>> Stream<T> readTableStream(ReadTableParams<ID>
533559 .stream ()
534560 .filter (e -> readTableFilter (e , params ));
535561 if (params .isOrdered ()) {
536- stream = stream .sorted (EntityIdSchema . SORT_ENTITY_BY_ID );
562+ stream = stream .sorted (getEntityByIdComparator ( schema ) );
537563 }
538564 if (params .getRowLimit () > 0 ) {
539565 stream = stream .limit (params .getRowLimit ());
@@ -542,18 +568,20 @@ private <ID extends Entity.Id<T>> Stream<T> readTableStream(ReadTableParams<ID>
542568 }
543569
544570 private <ID extends Entity .Id <T >> boolean readTableFilter (T e , ReadTableParams <ID > params ) {
571+ EntityIdSchema <ID > idSchema = schema .getIdSchema ();
572+
545573 @ SuppressWarnings ("unchecked" )
546574 ID id = (ID ) e .getId ();
547575 ID from = params .getFromKey ();
548576 if (from != null ) {
549- int compare = EntityIdSchema . ofEntity ( id . getType ()) .compare (id , from );
577+ int compare = idSchema .compare (id , from );
550578 if (params .isFromInclusive () ? compare < 0 : compare <= 0 ) {
551579 return false ;
552580 }
553581 }
554582 ID to = params .getToKey ();
555583 if (to != null ) {
556- int compare = EntityIdSchema . ofEntity ( id . getType ()) .compare (id , to );
584+ int compare = idSchema .compare (id , to );
557585 return params .isToInclusive () ? compare <= 0 : compare < 0 ;
558586 }
559587 return true ;
@@ -587,7 +615,12 @@ private static <V extends Table.View, T extends Entity<T>> V toView(
587615 }
588616
589617
590- @ Deprecated // Legacy. Using only for creating InMemoryTable. Use constructor of InMemoryTable instead
618+ /**
619+ * @deprecated Legacy class, used only for creating {@code InMemoryTable}.
620+ * This class will be removed in YOJ 3.0.0.
621+ * Please use other constructors of {@code InMemoryTable} instead.
622+ */
623+ @ Deprecated (forRemoval = true )
591624 public record DbMemory <T extends Entity <T >>(
592625 Class <T > type ,
593626 InMemoryRepositoryTransaction transaction
0 commit comments