6695-2.patch
new/src/com/goldencode/p2j/persist/AdaptiveQuery.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
335 | 335 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
336 | 336 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
337 | 337 |
** processing all the scopeables for each and every block. |
338 |
** RAA 20221010 Added method isAutoFetch() for when lazy fetching is intended. |
|
339 |
** RAA 20221027 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
340 |
** is intended. |
|
338 | 341 |
*/ |
339 | 342 | |
340 | 343 |
/* |
... | ... | |
3276 | 3279 |
protected void fetch(boolean available, LockType lockType, boolean errorIfNull) |
3277 | 3280 |
throws MissingRecordException |
3278 | 3281 |
{ |
3282 |
if (available && getResults().isAutoFetch()) |
|
3283 |
{ |
|
3284 |
return; |
|
3285 |
} |
|
3286 | ||
3279 | 3287 |
super.fetch(available, lockType, errorIfNull); |
3280 | 3288 |
|
3281 | 3289 |
if (!isScrolling() && !foundFirst && available && offEnd == OffEnd.NONE) |
... | ... | |
3790 | 3798 |
} |
3791 | 3799 |
|
3792 | 3800 |
/** |
3801 |
* Is the result delegate responsible for fetching? This is usually true when using |
|
3802 |
* query delegates which handle the fetching process already. |
|
3803 |
* |
|
3804 |
* @return {@code true} for complex results which also do the fetching |
|
3805 |
* |
|
3806 |
*/ |
|
3807 |
@Override |
|
3808 |
public boolean isAutoFetch() |
|
3809 |
{ |
|
3810 |
return true; |
|
3811 |
} |
|
3812 |
|
|
3813 |
/** |
|
3793 | 3814 |
* Get the array of objects at the current result row. |
3794 | 3815 |
* |
3795 | 3816 |
* @return Object array or <code>null</code>. |
3796 | 3817 |
*/ |
3797 | 3818 |
public Object[] get() |
3798 | 3819 |
{ |
3799 |
int len = buffers.length; |
|
3800 |
Object[] row = new Object[len]; |
|
3801 |
for (int i = 0; i < len; i++) |
|
3820 |
return get(null); |
|
3821 |
} |
|
3822 |
|
|
3823 |
/** |
|
3824 |
* Get the array of objects at the current result row if lazy fetching allows it. |
|
3825 |
* |
|
3826 |
* @param fetching |
|
3827 |
* The instance responsible with lazy fetching. |
|
3828 |
* @return Object array or <code>null</code>. |
|
3829 |
*/ |
|
3830 |
public Object[] get(LazyFetching fetching) |
|
3831 |
{ |
|
3832 |
// if lazy fetching is not intended at all or |
|
3833 |
// if lazy fetching is intended and getting the full record is OK |
|
3834 |
if (fetching == null || fetching.isFullRecordOk()) |
|
3802 | 3835 |
{ |
3803 |
row[i] = get(i); |
|
3836 |
int len = buffers.length; |
|
3837 |
Object[] row = new Object[len]; |
|
3838 |
for (int i = 0; i < len; i++) |
|
3839 |
{ |
|
3840 |
row[i] = get(i); |
|
3841 |
} |
|
3842 |
|
|
3843 |
return row; |
|
3804 | 3844 |
} |
3805 | 3845 |
|
3806 |
return row;
|
|
3846 |
throw new IllegalStateException("Lazy Fetching is used, but the record is already hydrated");
|
|
3807 | 3847 |
} |
3808 | 3848 |
|
3809 | 3849 |
/** |
new/src/com/goldencode/p2j/persist/PreselectQuery.java 2022-11-09 10:17:54 +0000 | ||
---|---|---|
585 | 585 |
** OM 20220530 Fixed flush of nursery (only the affected index). |
586 | 586 |
** OM 20220701 Flatten calls to initialize(). |
587 | 587 |
** CA 20221006 Added JMX instrumentation for query assemble. Refs #6814 |
588 |
** RAA 20221010 Added class PreselectLazyFetching which enables the possibility of lazy fetching |
|
589 |
** for Preselect queries on temporary no-undo tables. |
|
588 | 590 |
** CA 20221013 In 'repositionByID', if the row number is after the last row in the ResultSet, |
589 | 591 |
** assume an error (query off-end) and do not try to fetch the record. |
590 | 592 |
*/ |
... | ... | |
762 | 764 |
/** Has query been registered for resource cleanup? */ |
763 | 765 |
private boolean regCleaner = false; |
764 | 766 |
|
767 |
/** Instance of lazy fetching. */ |
|
768 |
private LazyFetching fetching = new PreselectLazyFetching(); |
|
769 |
|
|
765 | 770 |
/** Cleaner executed when this query's block is exit. */ |
766 | 771 |
private final Finalizable cleaner = new Finalizable() |
767 | 772 |
{ |
... | ... | |
5669 | 5674 |
} |
5670 | 5675 |
else |
5671 | 5676 |
{ |
5672 |
Object[] data = available ? results.get() : null; |
|
5673 |
coreFetch(data, lockType, errorIfNull, false); |
|
5677 |
if (!results.isAutoFetch()) |
|
5678 |
{ |
|
5679 |
Object[] data = available ? results.get(fetching) : null; |
|
5680 |
coreFetch(data, lockType, errorIfNull, false); |
|
5681 |
} |
|
5674 | 5682 |
|
5675 | 5683 |
if (available) |
5676 | 5684 |
{ |
... | ... | |
5732 | 5740 |
{ |
5733 | 5741 |
int recFetched = 0; |
5734 | 5742 |
Iterator<QueryComponent> iter = components(); |
5743 |
|
|
5735 | 5744 |
for (int i = 0; iter.hasNext(); i++) |
5736 | 5745 |
{ |
5737 | 5746 |
QueryComponent comp = iter.next(); |
5738 | 5747 |
RecordBuffer buffer = comp.getBuffer(); |
5748 | ||
5749 |
if (data != null && data[i] == null) |
|
5750 |
{ |
|
5751 |
recFetched++; |
|
5752 |
continue; |
|
5753 |
} |
|
5754 |
|
|
5739 | 5755 |
boolean dirtyCopy = false; |
5740 | 5756 |
Record dmo = null; |
5741 | 5757 |
LockType lt = lockType; |
... | ... | |
6669 | 6685 |
@Override |
6670 | 6686 |
public Object[] get() |
6671 | 6687 |
{ |
6672 |
return (cursor == 0) ? new Object[] { templateRowid } : null; |
|
6688 |
return get(null); |
|
6689 |
} |
|
6690 |
|
|
6691 |
/** |
|
6692 |
* Get the array of objects at the current result row if lazy fetching allows it. |
|
6693 |
* |
|
6694 |
* @param fetching |
|
6695 |
* The instance responsible with lazy fetching. |
|
6696 |
* @return Object array or {@code null}. |
|
6697 |
*/ |
|
6698 |
@Override |
|
6699 |
public Object[] get(LazyFetching fetching) |
|
6700 |
{ |
|
6701 |
if (cursor != 0) |
|
6702 |
return null; |
|
6703 |
|
|
6704 |
// if lazy fetching is not intended at all or |
|
6705 |
// if lazy fetching is intended and getting the full record is OK |
|
6706 |
if (fetching == null || fetching.isFullRecordOk()) |
|
6707 |
{ |
|
6708 |
return new Object[] { templateRowid }; |
|
6709 |
} |
|
6710 |
|
|
6711 |
throw new IllegalStateException("Lazy Fetching is used, but the record is already hydrated"); |
|
6673 | 6712 |
} |
6674 | 6713 |
|
6675 | 6714 |
/** |
... | ... | |
6791 | 6830 |
// else cursor is -1 (before), 0 (on single record), 1 (after) |
6792 | 6831 |
} |
6793 | 6832 |
} |
6833 |
|
|
6834 |
/** |
|
6835 |
* Class that implements the concept of {@link LazyFetching} for {@link PreselectQuery}. |
|
6836 |
* It provides a quick response as to whether a {@link Record} should be lazy fetched or not. |
|
6837 |
*/ |
|
6838 |
class PreselectLazyFetching |
|
6839 |
implements LazyFetching |
|
6840 |
{ |
|
6841 | ||
6842 |
/** |
|
6843 |
* Method to check if a {@link Record} should be fully/partially fetched or not. |
|
6844 |
* Fully fetched means that a {@code Record} should be retrieved from the database, |
|
6845 |
* partially fetched means that a {@code Record} should be retrieved from the cache. |
|
6846 |
* This method does not make the difference between fully and partially fetching. It only matters if |
|
6847 |
* the lazy fetching layer is being bypassed or not (what happens after that is not its job). |
|
6848 |
* |
|
6849 |
* This implementation is specific to this class because we compare the primary key of the existing |
|
6850 |
* record with the one that is about to be put in the {@link RecordBuffer}. |
|
6851 |
* For other types of Queries different implementations could be required. |
|
6852 |
* |
|
6853 |
* @param comp |
|
6854 |
* The number of the {@link QueryComponent} for which we check it's {@link RecordBuffer}. |
|
6855 |
* @param id |
|
6856 |
* The id of the {@code Record} that is about to be put in the {@code RecordBuffer}. |
|
6857 |
* @return {@code true} if a {@code Record} should be fully/partially fetched |
|
6858 |
* (does not matter which one), {@code false} otherwise. |
|
6859 |
*/ |
|
6860 |
@Override |
|
6861 |
public boolean shouldFetch(int comp, Long id) |
|
6862 |
{ |
|
6863 |
QueryComponent component = components.get(comp); |
|
6864 |
return component.checkFetching(id); |
|
6865 |
} |
|
6866 | ||
6867 |
/** |
|
6868 |
* Setter for the {@code oldId}, which is responsible with knowing the id of the |
|
6869 |
* last {@code Record} that was inside the {@link RecordBuffer}. |
|
6870 |
* |
|
6871 |
* @param comp |
|
6872 |
* The number of the {@link QueryComponent} for which we check it's {@code RecordBuffer}. |
|
6873 |
* @param id |
|
6874 |
* The id of the old {@code Record}. |
|
6875 |
*/ |
|
6876 |
@Override |
|
6877 |
public void setOldId(int comp, Long id) |
|
6878 |
{ |
|
6879 |
components.get(comp).setOldId(id); |
|
6880 |
} |
|
6881 | ||
6882 |
/** |
|
6883 |
* Method for checking if it is OK to retrieve the full record. Most of the times, the implementation |
|
6884 |
* of this method will return {@code true}. Only in very few cases, the retrieval of the full record |
|
6885 |
* will not benefit the cause. |
|
6886 |
* |
|
6887 |
* @return {@code true} if we are fine with working with the full record, {@code false} otherwise. |
|
6888 |
*/ |
|
6889 |
@Override |
|
6890 |
public boolean isFullRecordOk() |
|
6891 |
{ |
|
6892 |
return true; |
|
6893 |
} |
|
6894 |
|
|
6895 |
} |
|
6794 | 6896 |
} |
6795 | 6897 |
new/src/com/goldencode/p2j/persist/PresortCompoundQuery.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
30 | 30 |
** 012 OM 20180620 Added support for dynamically configured sort criteria. |
31 | 31 |
** 013 ECF 20181106 Added runtime support for {FIRST|LAST}-OF methods. |
32 | 32 |
** 014 ECF 20200906 New ORM implementation. |
33 |
** 015 RAA 20221027 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
34 |
** is intended. |
|
33 | 35 |
*/ |
34 | 36 | |
35 | 37 |
/* |
... | ... | |
90 | 92 |
import java.io.*; |
91 | 93 |
import java.util.*; |
92 | 94 |
import com.goldencode.p2j.persist.lock.*; |
95 |
import com.goldencode.p2j.persist.orm.*; |
|
93 | 96 |
import com.goldencode.p2j.util.*; |
94 | 97 | |
95 | 98 |
/** |
... | ... | |
651 | 654 |
*/ |
652 | 655 |
public Object[] get() |
653 | 656 |
{ |
654 |
return row; |
|
657 |
return get(null); |
|
658 |
} |
|
659 |
|
|
660 |
/** |
|
661 |
* Get the array of objects at the current result row if lazy fetching allows it. |
|
662 |
* |
|
663 |
* @param fetching |
|
664 |
* The instance responsible with lazy fetching. |
|
665 |
* @return Object array or <code>null</code>. |
|
666 |
*/ |
|
667 |
public Object[] get(LazyFetching fetching) |
|
668 |
{ |
|
669 |
// if lazy fetching is not intended at all or |
|
670 |
// if lazy fetching is intended and getting the full record is OK |
|
671 |
if (fetching == null || fetching.isFullRecordOk()) |
|
672 |
{ |
|
673 |
return row; |
|
674 |
} |
|
675 |
|
|
676 |
throw new IllegalStateException("Lazy Fetching is used, but the record is already hydrated"); |
|
655 | 677 |
} |
656 | 678 |
|
657 | 679 |
/** |
new/src/com/goldencode/p2j/persist/Presorter.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
34 | 34 |
** 016 ECF 20190427 Fixed results caching. |
35 | 35 |
** 017 ECF 20200906 New ORM implementation. |
36 | 36 |
** 018 CA 20210923 Fixed SortedResults, when the component retrieves only the DMO id. |
37 |
** 019 RAA 20221027 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
38 |
** is intended. |
|
37 | 39 |
*/ |
38 | 40 | |
39 | 41 |
/* |
... | ... | |
96 | 98 |
import java.util.function.*; |
97 | 99 |
import com.goldencode.p2j.util.*; |
98 | 100 |
import com.goldencode.p2j.persist.event.SessionListener; |
101 |
import com.goldencode.p2j.persist.orm.*; |
|
99 | 102 | |
100 | 103 |
/** |
101 | 104 |
* This helper class performs client-side (i.e., relative to the database |
... | ... | |
934 | 937 |
*/ |
935 | 938 |
public Object[] get() |
936 | 939 |
{ |
940 |
return get(null); |
|
941 |
} |
|
942 |
|
|
943 |
/** |
|
944 |
* Get the array of objects at the current result row if lazy fetching allows it. |
|
945 |
* |
|
946 |
* @param fetching |
|
947 |
* The instance responsible with lazy fetching. |
|
948 |
* @return Object array or <code>null</code>. |
|
949 |
*/ |
|
950 |
public Object[] get(LazyFetching fetching) |
|
951 |
{ |
|
937 | 952 |
if (scrolling) |
938 | 953 |
{ |
939 |
return super.get(); |
|
954 |
return super.get(fetching);
|
|
940 | 955 |
} |
941 | 956 |
else |
942 | 957 |
{ |
943 |
Object[] datum = (Object[]) currentRow; |
|
944 |
|
|
945 |
return datum; |
|
958 |
// if lazy fetching is not intended at all or |
|
959 |
// if lazy fetching is intended and getting the full record is OK |
|
960 |
if (fetching == null || fetching.isFullRecordOk()) |
|
961 |
{ |
|
962 |
Object[] datum = (Object[]) currentRow; |
|
963 |
return datum; |
|
964 |
} |
|
965 | ||
966 |
throw new IllegalStateException("Record is not hydrated and should be, in order to be used"); |
|
946 | 967 |
} |
947 | 968 |
} |
948 | 969 |
|
new/src/com/goldencode/p2j/persist/ProgressiveResults.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
138 | 138 |
** EVL 20190822 Adding NPE protection for isResultSetCached. |
139 | 139 |
** 039 ECF 20200419 Removed Hibernate dependencies. |
140 | 140 |
** 040 IAS 20220720 Fixed iteration logic (multiple iterations in different directions). |
141 |
** 041 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
142 |
** is intended. |
|
141 | 143 |
*/ |
142 | 144 | |
143 | 145 |
/* |
... | ... | |
199 | 201 |
import java.util.*; |
200 | 202 |
import java.util.logging.*; |
201 | 203 |
import com.goldencode.p2j.persist.event.*; |
204 |
import com.goldencode.p2j.persist.orm.*; |
|
202 | 205 |
import com.goldencode.p2j.util.*; |
203 | 206 |
import com.goldencode.p2j.util.ErrorManager; |
204 | 207 | |
... | ... | |
459 | 462 |
*/ |
460 | 463 |
public Object[] get() |
461 | 464 |
{ |
465 |
return get(null); |
|
466 |
} |
|
467 |
|
|
468 |
/** |
|
469 |
* Get the array of objects at the current result row. |
|
470 |
* |
|
471 |
* @param fetching |
|
472 |
* The instance responsible with lazy fetching. |
|
473 |
* @return Object array or <code>null</code>. |
|
474 |
*/ |
|
475 |
public Object[] get(LazyFetching fetching) |
|
476 |
{ |
|
462 | 477 |
if (position < 0) |
463 | 478 |
{ |
464 | 479 |
return null; |
465 | 480 |
} |
466 | 481 |
|
482 |
// we can use cache if lazy fetching is not intended at all or |
|
483 |
// if lazy fetching is intended and getting the full record is OK |
|
484 |
boolean canUseCache = fetching == null || fetching.isFullRecordOk(); |
|
485 |
|
|
467 | 486 |
// If we have a cache and it contains the requested record, retrieve from the cache. |
468 |
if (cache != null && position < cache.size()) |
|
487 |
if (canUseCache && cache != null && position < cache.size())
|
|
469 | 488 |
{ |
470 | 489 |
return cache.get(position); |
471 | 490 |
} |
... | ... | |
476 | 495 |
Results results = getResults(bracket); |
477 | 496 |
if (results != null) |
478 | 497 |
{ |
479 |
return results.get(); |
|
498 |
return results.get(fetching);
|
|
480 | 499 |
} |
481 | 500 |
} |
482 | 501 |
catch (Exception exc) |
new/src/com/goldencode/p2j/persist/QueryComponent.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
28 | 28 |
** 014 CA 20191009 Added where and sort clause translation in case of bound buffers. |
29 | 29 |
** 015 ECF 20200906 New ORM implementation. |
30 | 30 |
** 016 ECF 20210820 Retrofit for query substitution parameter preprocessing fixes. |
31 |
** 017 RAA 20221010 Added the possibility of checking if fetching is necessary for this component. |
|
31 | 32 |
*/ |
32 | 33 | |
33 | 34 |
/* |
... | ... | |
164 | 165 |
/** Index information string as it is returned by INDEX-INFORMATION. */ |
165 | 166 |
private String indexInfo = null; |
166 | 167 |
|
168 |
/** The id of the old Record that was in the buffer. */ |
|
169 |
private Long oldId = null; |
|
170 |
|
|
167 | 171 |
/** |
168 | 172 |
* The list of dynamic filters. These are filters added dynamically, at runtime and can also be |
169 | 173 |
* removed dynamically. |
... | ... | |
828 | 832 |
} |
829 | 833 |
|
830 | 834 |
/** |
835 |
* Method used for checking if fetching is necessary for this component. |
|
836 |
* |
|
837 |
* @param id |
|
838 |
* The id of the {@code Record} that will potentially be fetched. |
|
839 |
* @return true if the buffer needs to fetch this record, or false otherwise. |
|
840 |
*/ |
|
841 |
public boolean checkFetching(Long id) |
|
842 |
{ |
|
843 |
Record record = buffer.getCurrentRecord(); |
|
844 |
if (record == null) |
|
845 |
{ |
|
846 |
return true; |
|
847 |
} |
|
848 |
|
|
849 |
Long bufferId = record.primaryKey(); |
|
850 |
if (bufferId != null && id.equals(bufferId) && id.equals(oldId)) |
|
851 |
{ |
|
852 |
return false; |
|
853 |
} |
|
854 |
|
|
855 |
return true; |
|
856 |
} |
|
857 |
|
|
858 |
/** |
|
859 |
* Setter for the old record's id. |
|
860 |
* |
|
861 |
* @param id |
|
862 |
* The id of the record that was just fetched. |
|
863 |
*/ |
|
864 |
public void setOldId(Long id) |
|
865 |
{ |
|
866 |
oldId = id; |
|
867 |
} |
|
868 |
|
|
869 |
/** |
|
831 | 870 |
* Set the record buffer for this component's query. |
832 | 871 |
* |
833 | 872 |
* @param buffer |
new/src/com/goldencode/p2j/persist/Results.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
14 | 14 |
** 004 ECF 20190427 Fixed results caching. |
15 | 15 |
** 005 SVL 20191002 Added addRow. |
16 | 16 |
** 006 ECF 20200906 New ORM implementation. |
17 |
** 007 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
18 |
** is intended. |
|
17 | 19 |
*/ |
18 | 20 | |
19 | 21 |
/* |
... | ... | |
71 | 73 | |
72 | 74 |
package com.goldencode.p2j.persist; |
73 | 75 | |
76 |
import com.goldencode.p2j.persist.orm.*; |
|
77 | ||
74 | 78 |
/** |
75 | 79 |
* An abstraction layer between a joinable query implementation and its results. This interface |
76 | 80 |
* defines methods for manipulating a results set using a scrollable cursor paradigm. Each row |
... | ... | |
122 | 126 |
public boolean isLast(); |
123 | 127 |
|
124 | 128 |
/** |
129 |
* Is the result delegate responsible for fetching? This is usually true when using |
|
130 |
* query delegates which handle the fetching process already. |
|
131 |
* |
|
132 |
* @return {@code true} for complex results which also do the fetching. |
|
133 |
* |
|
134 |
*/ |
|
135 |
default public boolean isAutoFetch() |
|
136 |
{ |
|
137 |
return false; |
|
138 |
} |
|
139 |
|
|
140 |
/** |
|
125 | 141 |
* Get the array of objects at the current result row. |
126 | 142 |
* |
127 | 143 |
* @return Object array or {@code null}. |
... | ... | |
129 | 145 |
public Object[] get(); |
130 | 146 |
|
131 | 147 |
/** |
148 |
* Get the array of objects at the current result row. The default method involves no lazy fetching. |
|
149 |
* If lazy fetching is desired, then this method needs to be implemented. |
|
150 |
* |
|
151 |
* @param fetching |
|
152 |
* The instance responsible with lazy fetching. |
|
153 |
* @return Array of {@code Object}s and {@code null}s. |
|
154 |
*/ |
|
155 |
default public Object[] get(LazyFetching fetching) |
|
156 |
{ |
|
157 |
if (fetching != null) |
|
158 |
{ |
|
159 |
throw new IllegalStateException(this.getClass().getName() + |
|
160 |
" does not implement get() with onlyDifferences."); |
|
161 |
} |
|
162 |
return get(); |
|
163 |
} |
|
164 |
|
|
165 |
/** |
|
132 | 166 |
* Get the object at the current result row, at the specified column. |
133 | 167 |
* |
134 | 168 |
* @param column |
... | ... | |
241 | 275 |
{ |
242 | 276 |
throw new IllegalStateException("Cannot add a row for this type of results"); |
243 | 277 |
} |
244 |
} |
|
278 |
} |
new/src/com/goldencode/p2j/persist/ResultsAdapter.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
24 | 24 |
** to true. |
25 | 25 |
** 007 ECF 20190427 Fixed results caching. |
26 | 26 |
** 008 ECF 20200906 New ORM implementation. |
27 |
** 009 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
28 |
** is intended. |
|
27 | 29 |
*/ |
28 | 30 | |
29 | 31 |
/* |
... | ... | |
83 | 85 | |
84 | 86 |
import java.io.*; |
85 | 87 | |
88 |
import com.goldencode.p2j.persist.orm.*; |
|
89 | ||
86 | 90 |
/** |
87 | 91 |
* An implementation of the {@code Results} interface which delegates all work to another {@code |
88 | 92 |
* Results} implementation. A worker can be connected at any time using {@link #setResults}, or |
... | ... | |
203 | 207 |
} |
204 | 208 |
|
205 | 209 |
/** |
210 |
* Is the result delegate responsible for fetching? This is usually true when using |
|
211 |
* query delegates which handle the fetching process already. |
|
212 |
* |
|
213 |
* @return {@code true} for complex results which also do the fetching. |
|
214 |
* |
|
215 |
*/ |
|
216 |
@Override |
|
217 |
public boolean isAutoFetch() |
|
218 |
{ |
|
219 |
return results.isAutoFetch(); |
|
220 |
} |
|
221 |
|
|
222 |
/** |
|
206 | 223 |
* Get the array of objects at the current result row. |
207 | 224 |
* |
208 | 225 |
* @return Object array or {@code null}. |
... | ... | |
211 | 228 |
{ |
212 | 229 |
return results.get(); |
213 | 230 |
} |
231 | ||
232 |
/** |
|
233 |
* Get the array of objects at the current result row if lazy fetching allows it. |
|
234 |
* |
|
235 |
* @param fetching |
|
236 |
* The instance responsible with lazy fetching. |
|
237 |
* @return Object array or {@code null}. |
|
238 |
*/ |
|
239 |
public Object[] get(LazyFetching fetching) |
|
240 |
{ |
|
241 |
return results.get(fetching); |
|
242 |
} |
|
214 | 243 |
|
215 | 244 |
/** |
216 | 245 |
* Get the object at the current result row, at the specified column. |
... | ... | |
405 | 434 |
provider.provideNewResults(this); |
406 | 435 |
} |
407 | 436 |
} |
408 |
} |
|
437 |
} |
new/src/com/goldencode/p2j/persist/ScrollingResults.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
20 | 20 |
** first record (and we are actually on/before the first row). But, in postgresql |
21 | 21 |
** JDBC driver, doing a -1 scroll will position us on the last row (it circles |
22 | 22 |
** back from the last row if the value is negative!). |
23 |
** 009 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
24 |
** is intended. |
|
23 | 25 |
*/ |
24 | 26 | |
25 | 27 |
/* |
... | ... | |
197 | 199 |
} |
198 | 200 |
|
199 | 201 |
/** |
202 |
* Get an array of objects or nulls at the current result row if lazy fetching allows it. |
|
203 |
* |
|
204 |
* @param fetching |
|
205 |
* The instance responsible with lazy fetching. |
|
206 |
* @return Object array or <code>null</code>. |
|
207 |
*/ |
|
208 |
public Object[] get(LazyFetching fetching) |
|
209 |
{ |
|
210 |
return results.get(fetching); |
|
211 |
} |
|
212 |
|
|
213 |
/** |
|
200 | 214 |
* Get the object at the current result row, at the specified column. |
201 | 215 |
* |
202 | 216 |
* @param column |
new/src/com/goldencode/p2j/persist/SimpleResults.java 2022-11-09 10:12:47 +0000 | ||
---|---|---|
23 | 23 |
** 010 ECF 20190427 Fixed results caching. |
24 | 24 |
** 011 SVL 20191002 Added addRow. |
25 | 25 |
** 012 ECF 20200906 New ORM implementation. |
26 |
** 013 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching |
|
27 |
** is intended. |
|
26 | 28 |
*/ |
27 | 29 | |
28 | 30 |
/* |
... | ... | |
82 | 84 | |
83 | 85 |
import java.util.*; |
84 | 86 | |
87 |
import com.goldencode.p2j.persist.orm.*; |
|
88 | ||
85 | 89 |
/** |
86 | 90 |
* A simple implementation of {@code Results} which stores row data in a list provided to the |
87 | 91 |
* constructor. The row data consists of a list of array objects. Each object in the array is |
... | ... | |
209 | 213 |
*/ |
210 | 214 |
public Object[] get() |
211 | 215 |
{ |
216 |
return get(null); |
|
217 |
} |
|
218 |
|
|
219 |
/** |
|
220 |
* Get the array of objects at the current result row. |
|
221 |
* Because {@code SimpleResults} is meant to provide database results as fast as possible, |
|
222 |
* checks for Lazy Fetching are skipped here |
|
223 |
* (which also means that future implementations of Lazy Fetching here will not be considered). |
|
224 |
* |
|
225 |
* @param fetching |
|
226 |
* The instance responsible with lazy fetching. |
|
227 |
* @return Object array or {@code null}. |
|
228 |
*/ |
|
229 |
public Object[] get(LazyFetching fetching) |
|
230 |
{ |
|
212 | 231 |
if (position < 0 || position > getNumberOfLoadedRows() - 1) |
213 | 232 |
{ |
214 | 233 |
return null; |
215 | 234 |
} |
216 |
|
|
235 | ||
217 | 236 |
Object res = rows.get(position); |
218 | 237 |
if (res instanceof Object[]) |
219 | 238 |
{ |
... | ... | |
223 | 242 |
{ |
224 | 243 |
return new Object[] { res }; |
225 | 244 |
} |
226 |
} |
|
245 |
|
|
246 |
} |
|
227 | 247 |
|
228 | 248 |
/** |
229 | 249 |
* Get the object at the current result row, at the specified column. |
new/src/com/goldencode/p2j/persist/orm/LazyFetching.java 2022-11-03 12:09:26 +0000 | ||
---|---|---|
1 |
/* |
|
2 |
** Module : LazyFetching.java |
|
3 |
** Abstract : A layer between a Query and Results. |
|
4 |
** |
|
5 |
** Copyright (c) 2004-2022, Golden Code Development Corporation. |
|
6 |
** |
|
7 |
** -#- -I- --Date-- -----------------------------------Description----------------------------------- |
|
8 |
** 001 RAA 20221010 Added the concept of lazy fetching. This stands between the Query and its Results. |
|
9 |
* If the Query wishes to apply lazy fetching, then this interface needs to be implemented. |
|
10 |
* Implementations might differ, depending on how the results are being retrieved. |
|
11 |
* |
|
12 |
*/ |
|
13 | ||
14 |
/* |
|
15 |
** This program is free software: you can redistribute it and/or modify |
|
16 |
** it under the terms of the GNU Affero General Public License as |
|
17 |
** published by the Free Software Foundation, either version 3 of the |
|
18 |
** License, or (at your option) any later version. |
|
19 |
** |
|
20 |
** This program is distributed in the hope that it will be useful, |
|
21 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
22 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
23 |
** GNU Affero General Public License for more details. |
|
24 |
** |
|
25 |
** You may find a copy of the GNU Affero GPL version 3 at the following |
|
26 |
** location: https://www.gnu.org/licenses/agpl-3.0.en.html |
|
27 |
** |
|
28 |
** Additional terms under GNU Affero GPL version 3 section 7: |
|
29 |
** |
|
30 |
** Under Section 7 of the GNU Affero GPL version 3, the following additional |
|
31 |
** terms apply to the works covered under the License. These additional terms |
|
32 |
** are non-permissive additional terms allowed under Section 7 of the GNU |
|
33 |
** Affero GPL version 3 and may not be removed by you. |
|
34 |
** |
|
35 |
** 0. Attribution Requirement. |
|
36 |
** |
|
37 |
** You must preserve all legal notices or author attributions in the covered |
|
38 |
** work or Appropriate Legal Notices displayed by works containing the covered |
|
39 |
** work. You may not remove from the covered work any author or developer |
|
40 |
** credit already included within the covered work. |
|
41 |
** |
|
42 |
** 1. No License To Use Trademarks. |
|
43 |
** |
|
44 |
** This license does not grant any license or rights to use the trademarks |
|
45 |
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks |
|
46 |
** of Golden Code Development Corporation. You are not authorized to use the |
|
47 |
** name Golden Code, FWD, or the names of any author or contributor, for |
|
48 |
** publicity purposes without written authorization. |
|
49 |
** |
|
50 |
** 2. No Misrepresentation of Affiliation. |
|
51 |
** |
|
52 |
** You may not represent yourself as Golden Code Development Corporation or FWD. |
|
53 |
** |
|
54 |
** You may not represent yourself for publicity purposes as associated with |
|
55 |
** Golden Code Development Corporation, FWD, or any author or contributor to |
|
56 |
** the covered work, without written authorization. |
|
57 |
** |
|
58 |
** 3. No Misrepresentation of Source or Origin. |
|
59 |
** |
|
60 |
** You may not represent the covered work as solely your work. All modified |
|
61 |
** versions of the covered work must be marked in a reasonable way to make it |
|
62 |
** clear that the modified work is not originating from Golden Code Development |
|
63 |
** Corporation or FWD. All modified versions must contain the notices of |
|
64 |
** attribution required in this license. |
|
65 |
*/ |
|
66 | ||
67 |
package com.goldencode.p2j.persist.orm; |
|
68 | ||
69 |
import com.goldencode.p2j.persist.*; |
|
70 | ||
71 |
/** |
|
72 |
* Interface that defines the concept of lazy fetching. |
|
73 |
* This process appears between a Query and the retrieval of its Results. |
|
74 |
* The interface must be implemented accordingly, depending on the method of retrieving results. |
|
75 |
*/ |
|
76 |
public interface LazyFetching |
|
77 |
{ |
|
78 |
/** |
|
79 |
* Method to check if a {@link Record} should be fully/partially fetched or not. |
|
80 |
* Fully fetched means that a {@code Record} should be retrieved from the database, |
|
81 |
* partially fetched means that a {@code Record} should be retrieved from the cache. |
|
82 |
* This method does not make the difference between fully and partially fetching. It only matters if |
|
83 |
* the lazy fetching layer is being bypassed or not (what happens after that is not its job). |
|
84 |
* |
|
85 |
* @param comp |
|
86 |
* The number of the {@link QueryComponent} for which we check it's {@link RecordBuffer}. |
|
87 |
* @param id |
|
88 |
* The id of the {@code Record} that is about to be put in the {@code RecordBuffer}. |
|
89 |
* @return {@code true} if a {@code Record} should be fully/partially fetched |
|
90 |
* (does not matter which one), {@code false} otherwise. |
|
91 |
*/ |
|
92 |
public boolean shouldFetch(int comp, Long id); |
|
93 |
|
|
94 |
/** |
|
95 |
* Setter for the {@code oldId}, which is responsible with knowing the id of the |
|
96 |
* last {@code Record} that was inside the {@link RecordBuffer}. |
|
97 |
* |
|
98 |
* @param comp |
|
99 |
* The number of the {@link QueryComponent} for which we check it's {@code RecordBuffer}. |
|
100 |
* @param id |
|
101 |
* The id of the old {@code Record}. |
|
102 |
*/ |
|
103 |
public void setOldId(int comp, Long id); |
|
104 |
|
|
105 |
/** |
|
106 |
* Method for checking if it is OK to retrieve the full record. Most of the times, the implementation |
|
107 |
* of this method will return {@code true}. Only in very few cases, the retrieval of the full record |
|
108 |
* will not benefit the cause. |
|
109 |
* |
|
110 |
* @return {@code true} if we are fine with working with the full record, {@code false} otherwise. |
|
111 |
*/ |
|
112 |
public boolean isFullRecordOk(); |
|
113 |
} |
new/src/com/goldencode/p2j/persist/orm/ScrollableResults.java 2022-11-09 10:13:03 +0000 | ||
---|---|---|
8 | 8 |
** 001 ECF 20191001 Created initial version, with stubbed methods. |
9 | 9 |
** OM 20191111 Added method implementation. |
10 | 10 |
** 002 SBI 20220811 Added new version of get method to retrieve selected columns from a row. |
11 |
** 003 RAA 20221010 Added a 'get' method with a LazyFetching parameter for when lazy fetching is intended. |
|
11 | 12 |
** 20221023 Added a usage of SQLQuery.hydrateRecord(ResultSet, RowStructure, int, Session). |
12 | 13 |
*/ |
13 | 14 | |
... | ... | |
108 | 109 |
* @param session |
109 | 110 |
* The {@code Session} to be used. |
110 | 111 |
*/ |
111 |
public ScrollableResults(Statement stmt, ResultSet rs, List<RowStructure> rowStructure, Session session) |
|
112 |
public ScrollableResults(Statement stmt, |
|
113 |
ResultSet rs, |
|
114 |
List<RowStructure> rowStructure, |
|
115 |
Session session) |
|
112 | 116 |
{ |
113 | 117 |
this.stmt = stmt; |
114 | 118 |
this.rs = rs; |
... | ... | |
193 | 197 |
} |
194 | 198 |
|
195 | 199 |
/** |
196 |
* Obtain the full set of values on current row. An array of primary keys or full {@code Record} will be |
|
197 |
* returned. |
|
200 |
* Obtain the full set of values on current row. An array of primary keys or full {@code Record}s, |
|
201 |
* or {@code null}s will be returned. First two cases correspond to the need of fetching, |
|
202 |
* while {@code null} means that no fetching is necessary for that component. |
|
198 | 203 |
* |
204 |
* @param fetching |
|
205 |
* The instance responsible with lazy fetching. |
|
206 |
* |
|
199 | 207 |
* @return An array of {@code Object} s if the cursor is on a valid position. Otherwise {@code null} is |
200 | 208 |
* returned. The type of returned elements may be both {@code Long} when an array of PKs (recids) |
201 | 209 |
* is queried or an array of full {@code Record}s. The caller is responsible for handling both |
202 | 210 |
* cases (including hydration, if needed). |
203 | 211 |
*/ |
204 |
public Object[] get() |
|
212 |
public Object[] get(LazyFetching fetching)
|
|
205 | 213 |
{ |
214 |
|
|
206 | 215 |
return execute(() -> |
207 | 216 |
{ |
208 | 217 |
int rowSize = (rowStructure == null) ? 0 : rowStructure.size(); |
... | ... | |
228 | 237 |
ret = new Object[rowSize]; |
229 | 238 |
int rsOffset = 1; |
230 | 239 |
int recCnt = 0; |
240 |
|
|
231 | 241 |
for (RowStructure rowStruct : rowStructure) |
232 | 242 |
{ |
233 | 243 |
int expColumnCount = rowStruct.count; |
244 |
Long object = rs.getLong(rsOffset); |
|
245 |
|
|
246 |
//if fetching is not null, lazy fetching is intended |
|
247 |
if (fetching != null) |
|
248 |
{ |
|
249 |
if (object != null && !fetching.shouldFetch(recCnt, object)) |
|
250 |
{ |
|
251 |
ret[recCnt] = null; |
|
252 |
// position on next record |
|
253 |
rsOffset += expColumnCount; |
|
254 |
++recCnt; |
|
255 |
continue; |
|
256 |
} |
|
257 |
} |
|
258 |
|
|
234 | 259 |
try |
235 | 260 |
{ |
236 |
ret[recCnt] = |
|
237 |
SQLQuery.hydrateRecord(rs, rowStruct, rsOffset, session); |
|
261 |
ret[recCnt] = SQLQuery.hydrateRecord(rs, rowStruct, rsOffset, session); |
|
262 |
if (fetching != null) |
|
263 |
{ |
|
264 |
fetching.setOldId(recCnt, object); |
|
265 |
} |
|
238 | 266 |
} |
239 | 267 |
catch (PersistenceException e) |
240 | 268 |
{ |
... | ... | |
251 | 279 |
} |
252 | 280 |
|
253 | 281 |
/** |
282 |
* Obtain the full set of values on current row. An array of primary keys or full {@code Record} will be |
|
283 |
* returned. |
|
284 |
* |
|
285 |
* @return An array of {@code Object} s if the cursor is on a valid position. Otherwise {@code null} is |
|
286 |
* returned. The type of returned elements may be both {@code Long} when an array of PKs (recids) |
|
287 |
* is queried or an array of full {@code Record}s. The caller is responsible for handling both |
|
288 |
* cases (including hydration, if needed). |
|
289 |
*/ |
|
290 |
public Object[] get() |
|
291 |
{ |
|
292 |
return get(null); |
|
293 |
} |
|
294 |
|
|
295 |
/** |
|
254 | 296 |
* Obtain the selection of values on current row. |
255 | 297 |
* |
256 | 298 |
* @param dmoInfo |