11package tech .ydb .yoj .repository .db ;
22
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 ;
73import 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 ;
146
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 ;
207import 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- }
3208
9+ public interface Table <T extends Entity <T >> extends TableReader <T >, WriteTable <T > {
32110 default void bulkUpsert (List <T > input , BulkParams params ) {
32211 throw new UnsupportedOperationException ();
32312 }
32413
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-
35314 interface View {
35415 }
35516
@@ -361,7 +22,7 @@ interface ViewId<T extends Entity<T>> extends View {
36122 * Base interface for ID-aware table views that are Java {@link java.lang.Record records}.
36223 * <p>Forwards {@link ViewId#getId() ViewId's getId() method} to the record's {@code id()} accessor.
36324 *
364- * @param <E > entity type
25+ * @param <T > entity type
36526 */
36627 interface RecordViewId <T extends Entity <T >> extends ViewId <T > {
36728 Entity .Id <T > id ();
0 commit comments