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