1
1
package tech .ydb .yoj .repository .db ;
2
2
3
- import com .google .common .collect .Sets ;
4
- import lombok .NonNull ;
5
- import tech .ydb .yoj .databind .expression .FilterExpression ;
6
- import tech .ydb .yoj .databind .expression .OrderExpression ;
7
3
import tech .ydb .yoj .repository .db .bulk .BulkParams ;
8
- import tech .ydb .yoj .repository .db .cache .FirstLevelCache ;
9
- import tech .ydb .yoj .repository .db .list .ListRequest ;
10
- import tech .ydb .yoj .repository .db .list .ListResult ;
11
- import tech .ydb .yoj .repository .db .list .ViewListResult ;
12
- import tech .ydb .yoj .repository .db .readtable .ReadTableParams ;
13
- import tech .ydb .yoj .repository .db .statement .Changeset ;
4
+ import tech .ydb .yoj .repository .db .table .TableReader ;
5
+ import tech .ydb .yoj .repository .db .table .WriteTable ;
14
6
15
- import javax .annotation .CheckForNull ;
16
- import javax .annotation .Nullable ;
17
- import java .util .Collection ;
18
- import java .util .HashMap ;
19
- import java .util .HashSet ;
20
7
import java .util .List ;
21
- import java .util .Optional ;
22
- import java .util .Set ;
23
- import java .util .function .Function ;
24
- import java .util .function .Supplier ;
25
- import java .util .stream .Collectors ;
26
- import java .util .stream .Stream ;
27
-
28
- import static java .util .stream .Collectors .toList ;
29
- import static java .util .stream .Collectors .toSet ;
30
- import static java .util .stream .Stream .concat ;
31
-
32
- public interface Table <T extends Entity <T >> {
33
- <ID extends Entity .Id <T >> Stream <T > readTable (ReadTableParams <ID > params );
34
-
35
- <ID extends Entity .Id <T >> Stream <ID > readTableIds (ReadTableParams <ID > params );
36
-
37
- <V extends ViewId <T >, ID extends Entity .Id <T >> Stream <V > readTable (Class <V > viewClass , ReadTableParams <ID > params );
38
-
39
- Class <T > getType ();
40
-
41
- @ CheckForNull
42
- T find (Entity .Id <T > id );
43
-
44
- <V extends View > V find (Class <V > viewType , Entity .Id <T > id );
45
-
46
- <ID extends Entity .Id <T >> List <T > find (Range <ID > range );
47
-
48
- <ID extends Entity .Id <T >> List <ID > findIds (Range <ID > range );
49
-
50
- <ID extends Entity .Id <T >> List <ID > findIds (Set <ID > partialIds );
51
-
52
- <V extends View , ID extends Entity .Id <T >> List <V > find (Class <V > viewType , Range <ID > range );
53
-
54
- <V extends View , ID extends Entity .Id <T >> List <V > find (Class <V > viewType , Set <ID > ids );
55
-
56
- List <T > findAll ();
57
-
58
- <V extends View > List <V > findAll (Class <V > viewType );
59
-
60
- List <T > find (
61
- @ Nullable String indexName ,
62
- @ Nullable FilterExpression <T > filter ,
63
- @ Nullable OrderExpression <T > orderBy ,
64
- @ Nullable Integer limit ,
65
- @ Nullable Long offset
66
- );
67
-
68
- <ID extends Entity .Id <T >> List <ID > findIds (
69
- @ Nullable String indexName ,
70
- @ Nullable FilterExpression <T > filter ,
71
- @ Nullable OrderExpression <T > orderBy ,
72
- @ Nullable Integer limit ,
73
- @ Nullable Long offset
74
- );
75
-
76
- <V extends Table .View > List <V > find (
77
- Class <V > viewType ,
78
- @ Nullable String indexName ,
79
- @ Nullable FilterExpression <T > filter ,
80
- @ Nullable OrderExpression <T > orderBy ,
81
- @ Nullable Integer limit ,
82
- @ Nullable Long offset ,
83
- boolean distinct
84
- );
85
-
86
- <ID extends Entity .Id <T >> List <T > find (
87
- Set <ID > ids ,
88
- @ Nullable FilterExpression <T > filter ,
89
- @ Nullable OrderExpression <T > orderBy ,
90
- @ Nullable Integer limit
91
- );
92
-
93
- <ID extends Entity .Id <T >> List <T > findUncached (
94
- Set <ID > ids ,
95
- @ Nullable FilterExpression <T > filter ,
96
- @ Nullable OrderExpression <T > orderBy ,
97
- @ Nullable Integer limit
98
- );
99
-
100
- <V extends Table .View , ID extends Entity .Id <T >> List <V > find (
101
- Class <V > viewType ,
102
- Set <ID > ids ,
103
- @ Nullable FilterExpression <T > filter ,
104
- @ Nullable OrderExpression <T > orderBy ,
105
- @ Nullable Integer limit
106
- );
107
-
108
- <K > List <T > find (
109
- String indexName ,
110
- Set <K > keys ,
111
- @ Nullable FilterExpression <T > filter ,
112
- @ Nullable OrderExpression <T > orderBy ,
113
- @ Nullable Integer limit
114
- );
115
-
116
- <V extends Table .View , K > List <V > find (
117
- Class <V > viewType ,
118
- String indexName ,
119
- Set <K > keys ,
120
- @ Nullable FilterExpression <T > filter ,
121
- @ Nullable OrderExpression <T > orderBy ,
122
- @ Nullable Integer limit
123
- );
124
-
125
- Stream <T > streamAll (int batchSize );
126
-
127
- <V extends ViewId <T >> Stream <V > streamAll (Class <V > viewType , int batchSize );
128
-
129
- <ID extends Entity .Id <T >> Stream <T > streamPartial (ID partial , int batchSize );
130
-
131
- <ID extends Entity .Id <T >, V extends ViewId <T >> Stream <V > streamPartial (Class <V > viewType , ID partial , int batchSize );
132
-
133
- <ID extends Entity .Id <T >> Stream <ID > streamAllIds (int batchSize );
134
-
135
- <ID extends Entity .Id <T >> Stream <ID > streamPartialIds (ID partial , int batchSize );
136
-
137
- long count (String indexName , FilterExpression <T > filter );
138
-
139
- long countAll ();
140
-
141
- // Unsafe
142
- T insert (T t );
143
-
144
- // Unsafe
145
- T save (T t );
146
-
147
- // Unsafe: may delete only entity, but not its projections, if entity was not loaded
148
- void delete (Entity .Id <T > id );
149
-
150
- // Unsafe
151
- void deleteAll ();
152
-
153
- default Stream <T > readTable () {
154
- return readTable (ReadTableParams .getDefault ());
155
- }
156
-
157
- default <ID extends Entity .Id <T >> Stream <ID > readTableIds () {
158
- return readTableIds (ReadTableParams .getDefault ());
159
- }
160
-
161
- default FirstLevelCache getFirstLevelCache () {
162
- return null ;
163
- };
164
-
165
- @ NonNull
166
- default <X extends Exception > T find (Entity .Id <T > id , Supplier <? extends X > throwIfAbsent ) throws X {
167
- T found = find (id );
168
- if (found != null ) {
169
- return found ;
170
- } else {
171
- throw throwIfAbsent .get ();
172
- }
173
- }
174
-
175
- default T findOrDefault (Entity .Id <T > id , Supplier <T > defaultSupplier ) {
176
- T found = find (id );
177
- return found != null ? found : defaultSupplier .get ();
178
- }
179
-
180
- default <V extends View , X extends Exception > V find (Class <V > viewType , Entity .Id <T > id , Supplier <? extends X > throwIfAbsent ) throws X {
181
- V found = find (viewType , id );
182
- if (found != null ) {
183
- return found ;
184
- } else {
185
- throw throwIfAbsent .get ();
186
- }
187
- }
188
-
189
- default T modifyIfPresent (Entity .Id <T > id , Function <T , T > modify ) {
190
- return Optional .ofNullable (find (id ))
191
- .map (modify )
192
- .map (this ::save )
193
- .orElse (null );
194
- }
195
-
196
- default T generateAndSaveNew (@ NonNull Supplier <T > generator ) {
197
- for (int i = 0 ; i < 7 ; i ++) {
198
- T t = generator .get ();
199
- if (find (t .getId ()) == null ) {
200
- return save (t );
201
- }
202
- }
203
- throw new IllegalStateException ("Cannot generate unique entity id" );
204
- }
205
-
206
- default <X extends Throwable > T saveNewOrThrow (@ NonNull T t , @ NonNull Supplier <? extends X > alreadyExists ) throws X {
207
- if (find (t .getId ()) != null ) {
208
- throw alreadyExists .get ();
209
- }
210
- return save (t );
211
- }
212
-
213
- default <X extends Throwable > T updateExistingOrThrow (@ NonNull T t , @ NonNull Supplier <? extends X > notFound ) throws X {
214
- if (find (t .getId ()) == null ) {
215
- throw notFound .get ();
216
- }
217
- return save (t );
218
- }
219
-
220
- default T saveOrUpdate (@ NonNull T t ) {
221
- find (t .getId ());
222
- return save (t );
223
- }
224
-
225
- default T deleteIfExists (@ NonNull Entity .Id <T > id ) {
226
- T t = find (id );
227
- if (t != null ) {
228
- delete (id );
229
- }
230
- return t ;
231
- }
232
-
233
- default <ID extends Entity .Id <T >> void deleteAll (Set <ID > ids ) {
234
- find (ids );
235
- ids .forEach (this ::delete );
236
- }
237
-
238
- default <ID extends Entity .Id <T >> void deleteAll (Range <ID > range ) {
239
- find (range ).forEach (e -> delete (e .getId ()));
240
- }
241
-
242
- // Unsafe
243
- @ SuppressWarnings ("unchecked" )
244
- default void insert (T first , T ... rest ) {
245
- insertAll (concat (Stream .of (first ), Stream .of (rest )).collect (toList ()));
246
- }
247
-
248
- // Unsafe
249
- default void insertAll (Collection <? extends T > entities ) {
250
- entities .forEach (this ::insert );
251
- }
252
-
253
- // Unsafe
254
- default <ID extends Entity .Id <T >> void delete (Set <ID > ids ) {
255
- ids .forEach (this ::delete );
256
- }
257
-
258
- // Unsafe
259
- default <ID extends Entity .Id <T >> void delete (Range <ID > range ) {
260
- findIds (range ).forEach (this ::delete );
261
- }
262
-
263
- default ListResult <T > list (ListRequest <T > request ) {
264
- List <T > nextPage = toQueryBuilder (request ).find ();
265
- return ListResult .forPage (request , postLoad (nextPage ));
266
- }
267
-
268
- default <V extends Table .View > ViewListResult <T , V > list (Class <V > viewType , ListRequest <T > request ) {
269
- List <V > nextPage = toQueryBuilder (request ).find (viewType );
270
- return ViewListResult .forPage (request , viewType , nextPage );
271
- }
272
-
273
- default <ID extends Entity .Id <T >> List <T > find (Set <ID > ids ) {
274
- if (ids .isEmpty ()) {
275
- return List .of ();
276
- }
277
-
278
- var orderBy = EntityExpressions .defaultOrder (getType ());
279
- var cache = getFirstLevelCache ();
280
- var isPartialIdMode = ids .iterator ().next ().isPartial ();
281
-
282
- var foundInCache = ids .stream ()
283
- .filter (cache ::containsKey )
284
- .map (cache ::peek )
285
- .flatMap (Optional ::stream )
286
- .collect (Collectors .toMap (Entity ::getId , Function .identity ()));
287
- var remainingIds = Sets .difference (ids , foundInCache .keySet ());
288
- var foundInDb = findUncached (remainingIds , null , orderBy , null );
289
-
290
- var merged = new HashMap <Entity .Id <T >, T >();
291
-
292
- // some entries found in db with partial id query may already be in cache (after update/delete),
293
- // so we must return actual entries from cache
294
- for (var entry : foundInDb ) {
295
- var id = entry .getId ();
296
- if (cache .containsKey (id )) {
297
- var cached = cache .peek (id );
298
- cached .ifPresent (t -> merged .put (id , t ));
299
- // not present means marked as deleted in cache
300
- } else {
301
- merged .put (id , this .postLoad (entry ));
302
- }
303
- }
304
-
305
- // add entries found in cache and not fetched from db
306
- for (var pair : foundInCache .entrySet ()) {
307
- var id = pair .getKey ();
308
- var entry = pair .getValue ();
309
- merged .put (id , entry );
310
- }
311
-
312
- if (!isPartialIdMode ) {
313
- Set <Entity .Id <T >> foundInDbIds = foundInDb .stream ().map (Entity ::getId ).collect (toSet ());
314
- Set <Entity .Id <T >> foundInCacheIds = new HashSet <>(foundInCache .keySet ());
315
- Sets .difference (Sets .difference (ids , foundInDbIds ), foundInCacheIds ).forEach (cache ::putEmpty );
316
- }
317
-
318
- return merged .values ().stream ().sorted (EntityIdSchema .SORT_ENTITY_BY_ID ).collect (Collectors .toList ());
319
- }
320
8
9
+ public interface Table <T extends Entity <T >> extends TableReader <T >, WriteTable <T > {
321
10
default void bulkUpsert (List <T > input , BulkParams params ) {
322
11
throw new UnsupportedOperationException ();
323
12
}
324
13
325
- default TableQueryBuilder <T > toQueryBuilder (ListRequest <T > request ) {
326
- return query ()
327
- .index (request .getIndex ())
328
- .filter (request .getFilter ())
329
- .orderBy (request .getOrderBy ())
330
- .offset (request .getOffset ())
331
- .limit (request .getPageSize () + 1 );
332
- }
333
-
334
- default List <T > postLoad (List <T > list ) {
335
- return list .stream ().map (this ::postLoad ).collect (Collectors .toList ());
336
- }
337
-
338
- default T postLoad (T e ) {
339
- return e .postLoad ();
340
- }
341
-
342
- default long count (FilterExpression <T > filter ) {
343
- return count (null , filter );
344
- }
345
-
346
- default TableQueryBuilder <T > query () {
347
- return new TableQueryBuilder <>(this );
348
- }
349
-
350
- @ Deprecated
351
- void update (Entity .Id <T > id , Changeset changeset );
352
-
353
14
interface View {
354
15
}
355
16
@@ -361,7 +22,7 @@ interface ViewId<T extends Entity<T>> extends View {
361
22
* Base interface for ID-aware table views that are Java {@link java.lang.Record records}.
362
23
* <p>Forwards {@link ViewId#getId() ViewId's getId() method} to the record's {@code id()} accessor.
363
24
*
364
- * @param <E > entity type
25
+ * @param <T > entity type
365
26
*/
366
27
interface RecordViewId <T extends Entity <T >> extends ViewId <T > {
367
28
Entity .Id <T > id ();
0 commit comments