3
3
import com .google .common .base .Preconditions ;
4
4
import com .google .common .collect .Iterables ;
5
5
import com .google .common .collect .Sets ;
6
+ import tech .ydb .yoj .DeprecationWarnings ;
6
7
import tech .ydb .yoj .databind .expression .FilterExpression ;
7
8
import tech .ydb .yoj .databind .expression .OrderExpression ;
8
9
import tech .ydb .yoj .databind .schema .ObjectSchema ;
14
15
import tech .ydb .yoj .repository .db .Range ;
15
16
import tech .ydb .yoj .repository .db .Table ;
16
17
import tech .ydb .yoj .repository .db .TableDescriptor ;
18
+ import tech .ydb .yoj .repository .db .TableQueryBuilder ;
17
19
import tech .ydb .yoj .repository .db .TableQueryImpl ;
18
20
import tech .ydb .yoj .repository .db .ViewSchema ;
19
21
import tech .ydb .yoj .repository .db .cache .FirstLevelCache ;
32
34
import static java .util .stream .Collectors .toList ;
33
35
import static java .util .stream .Collectors .toUnmodifiableMap ;
34
36
import static java .util .stream .Collectors .toUnmodifiableSet ;
37
+ import static tech .ydb .yoj .repository .db .TableQueryImpl .getEntityByIdComparator ;
35
38
36
39
public class InMemoryTable <T extends Entity <T >> implements Table <T > {
37
40
private final EntitySchema <T > schema ;
38
41
private final TableDescriptor <T > tableDescriptor ;
39
42
private final InMemoryRepositoryTransaction transaction ;
40
43
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 )
42
49
public InMemoryTable (DbMemory <T > memory ) {
43
50
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" );
44
53
}
45
54
46
55
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 ;
48
59
}
49
60
50
61
public InMemoryTable (InMemoryRepositoryTransaction transaction , TableDescriptor <T > tableDescriptor ) {
@@ -53,6 +64,11 @@ public InMemoryTable(InMemoryRepositoryTransaction transaction, TableDescriptor<
53
64
this .transaction = transaction ;
54
65
}
55
66
67
+ @ Override
68
+ public TableQueryBuilder <T > query () {
69
+ return new TableQueryBuilder <>(this , schema );
70
+ }
71
+
56
72
@ Override
57
73
public List <T > findAll () {
58
74
transaction .getWatcher ().markTableRead (tableDescriptor );
@@ -103,7 +119,7 @@ public List<T> find(
103
119
@ Nullable Long offset
104
120
) {
105
121
// 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 );
107
123
}
108
124
109
125
@ Override
@@ -173,8 +189,8 @@ public TableDescriptor<T> getTableDescriptor() {
173
189
174
190
@ Override
175
191
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" );
178
194
}
179
195
return transaction .getTransactionLocal ().firstLevelCache (tableDescriptor ).get (id , __ -> {
180
196
markKeyRead (id );
@@ -185,13 +201,13 @@ public T find(Entity.Id<T> id) {
185
201
186
202
@ Override
187
203
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 );
189
205
}
190
206
191
207
@ Override
192
208
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" );
195
211
}
196
212
197
213
FirstLevelCache <T > cache = transaction .getTransactionLocal ().firstLevelCache (tableDescriptor );
@@ -208,10 +224,13 @@ public <V extends View> V find(Class<V> viewType, Entity.Id<T> id) {
208
224
@ Override
209
225
@ SuppressWarnings ("unchecked" )
210
226
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 );
212
231
return findAll0 ().stream ()
213
232
.filter (e -> range .contains ((ID ) e .getId ()))
214
- .sorted (EntityIdSchema . SORT_ENTITY_BY_ID )
233
+ .sorted (getEntityByIdComparator ( schema ) )
215
234
.collect (toList ());
216
235
}
217
236
@@ -232,7 +251,7 @@ public <V extends View, ID extends Entity.Id<T>> List<V> find(Class<V> viewType,
232
251
233
252
@ Override
234
253
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 );
236
255
}
237
256
238
257
@ Override
@@ -404,9 +423,10 @@ private boolean isPrefixedFields(List<String> keyFields, Set<String> fields) {
404
423
405
424
private <ID extends Entity .Id <T >> void markKeyRead (ID id ) {
406
425
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 ()) {
408
428
// 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 ));
410
430
} else {
411
431
transaction .getWatcher ().markRowRead (tableDescriptor , id );
412
432
}
@@ -475,7 +495,7 @@ public <ID extends Entity.Id<T>> Stream<T> streamPartial(ID partial, int batchSi
475
495
Preconditions .checkArgument (1 <= batchSize && batchSize <= 5000 ,
476
496
"batchSize must be in range [1, 5000], got %s" , batchSize );
477
497
478
- Range <ID > range = partial == null ? null : Range . create (partial );
498
+ Range <ID > range = rangeForPartialId (partial );
479
499
markRangeRead (range );
480
500
481
501
return streamPartial0 (range );
@@ -508,20 +528,26 @@ public <ID extends Entity.Id<T>> Stream<ID> streamPartialIds(ID partial, int bat
508
528
Preconditions .checkArgument (1 <= batchSize && batchSize <= 10000 ,
509
529
"batchSize must be in range [1, 10000], got %s" , batchSize );
510
530
511
- Range <ID > range = partial == null ? null : Range . create (partial );
531
+ Range <ID > range = rangeForPartialId (partial );
512
532
markRangeRead (range );
513
533
514
534
return streamPartial0 (range ).map (e -> (ID ) e .getId ());
515
535
}
516
536
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 ) {
518
538
if (range == null ) {
519
539
transaction .getWatcher ().markTableRead (tableDescriptor );
520
540
} else {
521
541
transaction .getWatcher ().markRangeRead (tableDescriptor , range );
522
542
}
523
543
}
524
544
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
+
525
551
private <ID extends Entity .Id <T >> Stream <T > readTableStream (ReadTableParams <ID > params ) {
526
552
if (!transaction .getOptions ().getIsolationLevel ().isReadOnly ()) {
527
553
throw new IllegalTransactionIsolationLevelException ("readTable" , transaction .getOptions ().getIsolationLevel ());
@@ -533,7 +559,7 @@ private <ID extends Entity.Id<T>> Stream<T> readTableStream(ReadTableParams<ID>
533
559
.stream ()
534
560
.filter (e -> readTableFilter (e , params ));
535
561
if (params .isOrdered ()) {
536
- stream = stream .sorted (EntityIdSchema . SORT_ENTITY_BY_ID );
562
+ stream = stream .sorted (getEntityByIdComparator ( schema ) );
537
563
}
538
564
if (params .getRowLimit () > 0 ) {
539
565
stream = stream .limit (params .getRowLimit ());
@@ -542,18 +568,20 @@ private <ID extends Entity.Id<T>> Stream<T> readTableStream(ReadTableParams<ID>
542
568
}
543
569
544
570
private <ID extends Entity .Id <T >> boolean readTableFilter (T e , ReadTableParams <ID > params ) {
571
+ EntityIdSchema <ID > idSchema = schema .getIdSchema ();
572
+
545
573
@ SuppressWarnings ("unchecked" )
546
574
ID id = (ID ) e .getId ();
547
575
ID from = params .getFromKey ();
548
576
if (from != null ) {
549
- int compare = EntityIdSchema . ofEntity ( id . getType ()) .compare (id , from );
577
+ int compare = idSchema .compare (id , from );
550
578
if (params .isFromInclusive () ? compare < 0 : compare <= 0 ) {
551
579
return false ;
552
580
}
553
581
}
554
582
ID to = params .getToKey ();
555
583
if (to != null ) {
556
- int compare = EntityIdSchema . ofEntity ( id . getType ()) .compare (id , to );
584
+ int compare = idSchema .compare (id , to );
557
585
return params .isToInclusive () ? compare <= 0 : compare < 0 ;
558
586
}
559
587
return true ;
@@ -587,7 +615,12 @@ private static <V extends Table.View, T extends Entity<T>> V toView(
587
615
}
588
616
589
617
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 )
591
624
public record DbMemory <T extends Entity <T >>(
592
625
Class <T > type ,
593
626
InMemoryRepositoryTransaction transaction
0 commit comments