6720_good.patch
| new/rules/schema/java_pojo.xml 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 3 | 3 |
** Module : java_dmo.xml |
| 4 | 4 |
** Abstract : walks data model AST and generates Java AST for each class node |
| 5 | 5 |
** |
| 6 |
** Copyright (c) 2022-2026, Golden Code Development Corporation.
|
|
| 6 |
** Copyright (c) 2022, Golden Code Development Corporation. |
|
| 7 | 7 |
** |
| 8 | 8 |
** _#_ _I_ __Date__ _______________________________________Description_______________________________________ |
| 9 | 9 |
** 001 OM 20220707 First commit with basic implementation. |
| 10 |
** 002 RNC 20260406 Migrate RECID from 32-bit to 64-bit values. |
|
| 11 | 10 |
--> |
| 12 | 11 | |
| 13 | 12 |
<!-- |
| ... | ... | |
| 113 | 112 |
<rule>typeMapping.put("logical", "Boolean")</rule>
|
| 114 | 113 |
<rule>typeMapping.put("object", "Long")</rule>
|
| 115 | 114 |
<rule>typeMapping.put("raw", "byte[]")</rule>
|
| 116 |
<rule>typeMapping.put("recid", "Long")</rule>
|
|
| 115 |
<rule>typeMapping.put("recid", "Integer")</rule>
|
|
| 117 | 116 |
<rule>typeMapping.put("rowid", "Long")</rule>
|
| 118 | 117 |
|
| 119 | 118 |
<rule>importPacks = create("java.util.HashSet")</rule>
|
| new/rules/schema/p2o.xml 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 312 | 312 |
** if this is specified in cfg file. |
| 313 | 313 |
** SP 20250324 Removed support for custom denormalized extents. |
| 314 | 314 |
** 108 SP 20250714 Fixed column collision check for expanded extent fields. |
| 315 |
** 109 RNC 20260409 Migrate RECID from 32-bit to 64-bit values. |
|
| 316 | 315 |
--> |
| 317 | 316 | |
| 318 | 317 |
<!-- |
| ... | ... | |
| 504 | 503 |
<rule>dataTypes.put(prog.field_int64, 'int64' )</rule> |
| 505 | 504 |
<rule>dataTypes.put(prog.field_logical, 'logical' )</rule> |
| 506 | 505 |
<rule>dataTypes.put(prog.field_raw, 'raw' )</rule> |
| 507 |
<rule>dataTypes.put(prog.field_recid, 'recid' )</rule>
|
|
| 506 |
<rule>dataTypes.put(prog.field_recid, 'integer' )</rule>
|
|
| 508 | 507 |
<rule>dataTypes.put(prog.field_rowid, 'rowid' )</rule> |
| 509 | 508 |
<rule>dataTypes.put(prog.field_class, 'object<? extends _BaseObject_>')</rule> |
| 510 | 509 |
|
| ... | ... | |
| 1741 | 1740 |
<rule> |
| 1742 | 1741 |
type == prog.field_int or |
| 1743 | 1742 |
type == prog.field_date or |
| 1743 |
type == prog.field_recid or |
|
| 1744 | 1744 |
type == prog.field_handle |
| 1745 | 1745 |
<action>sqlWidth = #(long) 4</action> |
| 1746 | 1746 |
</rule> |
| ... | ... | |
| 1750 | 1750 |
<!-- TODO: determine the proper length --> |
| 1751 | 1751 |
<action>sqlWidth = #(long) -1</action> |
| 1752 | 1752 |
</rule> |
| 1753 |
<rule>type == prog.field_rowid or |
|
| 1754 |
type == prog.field_recid |
|
| 1753 |
<rule>type == prog.field_rowid |
|
| 1755 | 1754 |
<action>sqlWidth = #(long) 8</action> |
| 1756 | 1755 |
</rule> |
| 1757 | 1756 |
<rule>type == prog.field_char |
| new/src/com/goldencode/p2j/jmx/FwdServerJMX.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 248 | 248 |
OrmDataSetParam, |
| 249 | 249 |
/** Instrumentation for <code>DataSet.createDynamicDataSet</code>. */ |
| 250 | 250 |
OrmDynamicDataSetParam, |
| 251 |
|
|
| 252 |
/** Lazily hydrated an new record (not rehydrated from cache) */ |
|
| 253 |
HydratorNewRecord, |
|
| 254 |
/** Lazily hydrated a record (including rehydration from cache) */ |
|
| 255 |
HydratorLazyRecord, |
|
| 256 |
/** Fully or partially hydrated a record, but not lazy */ |
|
| 257 |
HydratorNonLazyRecord, |
|
| 258 |
/** The hydrator token matched the result-set token */ |
|
| 259 |
HydratorHit, |
|
| 260 |
/** The hydrator token mismatched the result-set token */ |
|
| 261 |
HydratorMiss, |
|
| 262 |
/** The hydrator fallbacked to refresh and succeeded */ |
|
| 263 |
HyratorSuccessfullRefresh, |
|
| 264 |
/** The hydrator fallbacked to refresh and failed */ |
|
| 265 |
HyratorUnsuccessfullRefresh, |
|
| 266 |
/** Created a {@code ScrollableResults} instance with lazy results */
|
|
| 267 |
HydratorLazyScrollable, |
|
| 268 |
/** Created a {@code ScrollableResults} instance without lazy results */
|
|
| 269 |
HydratorNonLazyScrollable, |
|
| 270 |
/** Executed uniqueResult instance with lazy results */ |
|
| 271 |
HydratorLazyUnique, |
|
| 272 |
/** Executed uniqueResult instance without lazy results */ |
|
| 273 |
HydratorNonLazyUnique, |
|
| 251 | 274 | |
| 252 | 275 |
/** Instrumentation for <code>OutputTableCopier.finished</code> */ |
| 253 | 276 |
OutputTableCopier, |
| ... | ... | |
| 489 | 512 |
public static enum Counter |
| 490 | 513 |
implements OptionalCounter |
| 491 | 514 |
{
|
| 515 |
TempTotalFields, |
|
| 516 |
PersistentTotalFields, |
|
| 517 |
TempHydratedRecordsWhenSessionCloses, |
|
| 518 |
PersistentHydratedRecordsWhenSessionCloses, |
|
| 519 |
TempHydratedFieldsWhenSessionCloses, |
|
| 520 |
PersistentHydratedFieldsWhenSessionCloses, |
|
| 521 |
PersistentHydratedFieldsWithLZS, |
|
| 522 |
PersistentHydratedFieldsWithLoader, |
|
| 523 |
TempHydratedFieldsWithLZS, |
|
| 524 |
TempHydratedFieldsWithLoader, |
|
| 525 |
|
|
| 526 |
|
|
| 527 |
/** Lazily hydrated an new record (not rehydrated from cache) */ |
|
| 528 |
HydratorNewRecord, |
|
| 529 |
/** Lazily hydrated a record (including rehydration from cache) */ |
|
| 530 |
HydratorLazyRecord, |
|
| 531 |
/** Fully or partially hydrated a record, but not lazy */ |
|
| 532 |
HydratorNonLazyRecord, |
|
| 533 |
/** The hydrator token matched the result-set token */ |
|
| 534 |
HydratorHit, |
|
| 535 |
/** The hydrator token mismatched the result-set token */ |
|
| 536 |
HydratorMiss, |
|
| 537 |
/** The hydrator fallbacked to refresh and succeeded */ |
|
| 538 |
HyratorSuccessfullRefresh, |
|
| 539 |
/** The hydrator fallbacked to refresh and failed */ |
|
| 540 |
HyratorUnsuccessfullRefresh, |
|
| 541 |
/** Created a {@code ScrollableResults} instance with lazy results */
|
|
| 542 |
HydratorLazyScrollable, |
|
| 543 |
/** Created a {@code ScrollableResults} instance without lazy results */
|
|
| 544 |
HydratorNonLazyScrollable, |
|
| 545 |
/** Executed uniqueResult instance with lazy results */ |
|
| 546 |
HydratorLazyUnique, |
|
| 547 |
/** Executed uniqueResult instance without lazy results */ |
|
| 548 |
HydratorNonLazyUnique, |
|
| 549 |
|
|
| 492 | 550 |
/** Incomning network traffic */ |
| 493 | 551 |
NetworkReads, |
| 494 | 552 |
/** Outgoing network traffic */ |
| new/src/com/goldencode/p2j/persist/BufferImpl.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 1030 | 1030 |
* Get the record ID of the current buffer's current record, if any. P2J |
| 1031 | 1031 |
* implementation of the RECID function. |
| 1032 | 1032 |
* <p> |
| 1033 |
* This method will return a 64-bit recid which represents the internal |
|
| 1034 |
* row ID of the given record. |
|
| 1033 |
* This method will return a 32-bit recid which represents the internal |
|
| 1034 |
* row ID of the given record. If the actual row ID (which is implemented |
|
| 1035 |
* as a wider integer) cannot fit due to overflow, an error condition will |
|
| 1036 |
* be raised. |
|
| 1035 | 1037 |
* |
| 1036 | 1038 |
* @return Record ID of the underlying data record. If no record currently |
| 1037 | 1039 |
* backs the buffer associated with <code>dmo</code>, a recid |
| 1038 | 1040 |
* initialized as unknown value is returned. |
| 1041 |
* |
|
| 1042 |
* @throws ErrorConditionException |
|
| 1043 |
* if the actual record ID is too wide to fit within a 32-bit |
|
| 1044 |
* integer. |
|
| 1039 | 1045 |
*/ |
| 1040 | 1046 |
public recid recordID() |
| 1041 | 1047 |
{
|
| new/src/com/goldencode/p2j/persist/Cursor.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 77 | 77 |
** account for the case when its state can become invalid. Refs #9402. |
| 78 | 78 |
** 032 AL2 20250415 Allow consumers of repositionByID to decide if it should be a scan or not. |
| 79 | 79 |
** 033 AL2 20250521 Repositioning to a row is done with NO_LOCK. |
| 80 |
** 034 RNC 20260401 Modified method 'repositionByID()' to use a 64-bit integer. |
|
| 81 | 80 |
*/ |
| 82 | 81 | |
| 83 | 82 |
/* |
| ... | ... | |
| 263 | 262 |
* @throws ErrorConditionException |
| 264 | 263 |
* if the specified ID represents the unknown value. |
| 265 | 264 |
*/ |
| 266 |
boolean repositionByID(boolean scan, int64 id)
|
|
| 265 |
boolean repositionByID(boolean scan, integer id)
|
|
| 267 | 266 |
{
|
| 268 | 267 |
Long[] serIDs = new Long[] { id.longValue() };
|
| 269 | 268 |
|
| new/src/com/goldencode/p2j/persist/FqlType.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 2 | 2 |
** Module : FqlType.java |
| 3 | 3 |
** Abstract : Enumeration of data types for various SQL constructs |
| 4 | 4 |
** |
| 5 |
** Copyright (c) 2004-2026, Golden Code Development Corporation.
|
|
| 5 |
** Copyright (c) 2004-2020, Golden Code Development Corporation.
|
|
| 6 | 6 |
** |
| 7 | 7 |
** -#- -I- --Date-- --JPRM-- -----------------------------Description----------------------------- |
| 8 | 8 |
** 001 ECF 20080310 @37500 Created initial version. Enumeration of data types for various HQL |
| ... | ... | |
| 11 | 11 |
** 003 SVL 20120331 Added DATETIME and DATETIMETZ types. |
| 12 | 12 |
** 004 OM 20200402 Renamed class to FqlType and move to persist package. |
| 13 | 13 |
** 005 IAS 20201123 Added ARRAY type |
| 14 |
** 006 RNC 20260401 Modified the underlying recid class to use BIGINT instead of INTEGER. |
|
| 15 | 14 |
*/ |
| 16 | 15 | |
| 17 | 16 |
/* |
| ... | ... | |
| 120 | 119 |
types.put(comhandle.class, Types.VARCHAR); |
| 121 | 120 |
types.put(handle.class , Types.VARCHAR); |
| 122 | 121 |
types.put(object.class , Types.VARCHAR); |
| 123 |
types.put(recid.class , Types.BIGINT);
|
|
| 122 |
types.put(recid.class , Types.INTEGER);
|
|
| 124 | 123 |
types.put(rowid.class , Types.BIGINT); |
| 125 | 124 |
*/ |
| 126 | 125 |
|
| new/src/com/goldencode/p2j/persist/Persistence.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 751 | 751 |
import java.util.function.*; |
| 752 | 752 |
import java.util.logging.*; |
| 753 | 753 |
import com.goldencode.cache.*; |
| 754 |
import com.goldencode.p2j.jmx.*; |
|
| 754 | 755 |
import com.goldencode.p2j.persist.deploy.*; |
| 755 | 756 |
import com.goldencode.p2j.persist.dialect.*; |
| 756 | 757 |
import com.goldencode.p2j.persist.dirty.DirtyShareSupport; |
| ... | ... | |
| 1947 | 1948 |
{
|
| 1948 | 1949 |
local.closeSession(true); |
| 1949 | 1950 |
ErrorEntry ee = exc.getErrorEntry(); |
| 1950 |
ErrorManager.recordOrShowError( |
|
| 1951 |
new int[] {ee.num},
|
|
| 1952 |
new String[] {ee.text},
|
|
| 1953 |
true, |
|
| 1954 |
ee.prefix, |
|
| 1955 |
false, |
|
| 1956 |
false, |
|
| 1957 |
false, |
|
| 1958 |
true); |
|
| 1951 |
ErrorManager.recordOrShowError(new int[] {ee.num},
|
|
| 1952 |
new String[] {ee.text},
|
|
| 1953 |
true, |
|
| 1954 |
ee.prefix, |
|
| 1955 |
false, |
|
| 1956 |
false, |
|
| 1957 |
false, |
|
| 1958 |
true); |
|
| 1959 | 1959 |
handleException(ErrorManager.buildErrorText(ee.num, ee.text, ee.prefix, false), exc); |
| 1960 | 1960 |
} |
| 1961 | 1961 |
catch (PersistenceException exc) |
| ... | ... | |
| 5248 | 5248 |
/** FQL statement */ |
| 5249 | 5249 |
private final String fql; |
| 5250 | 5250 |
|
| 5251 |
/** Database dialect */ |
|
| 5252 |
private final Dialect dialect; |
|
| 5253 |
|
|
| 5251 | 5254 |
/** Does the query was generated with maximum results option? */ |
| 5252 | 5255 |
private final boolean hasMaxResults; |
| 5253 | 5256 |
|
| ... | ... | |
| 5268 | 5271 |
* |
| 5269 | 5272 |
* @param hql |
| 5270 | 5273 |
* FQL statement |
| 5274 |
* @param dialect |
|
| 5275 |
* Database dialect. |
|
| 5271 | 5276 |
* @param maxResults |
| 5272 | 5277 |
* Maximum results. |
| 5273 | 5278 |
* @param startOffset |
| 5274 | 5279 |
* Starting row offset. |
| 5275 | 5280 |
*/ |
| 5276 |
QueryKey(String hql, int maxResults, int startOffset, DataRelation relation, boolean lazyMode) |
|
| 5281 |
QueryKey(String hql, Dialect dialect, int maxResults, int startOffset, DataRelation relation, boolean lazyMode)
|
|
| 5277 | 5282 |
{
|
| 5278 | 5283 |
this.fql = hql; |
| 5284 |
this.dialect = dialect; |
|
| 5279 | 5285 |
this.hasMaxResults = maxResults > 0; |
| 5280 | 5286 |
this.hasStartOffset = startOffset > 0; |
| 5281 | 5287 |
this.whereStr = relation == null ? "" : relation.getWhereString().toJavaType(); |
| 5282 | 5288 |
this.lazyMode = lazyMode; |
| 5283 | 5289 |
|
| 5284 | 5290 |
int result = 17; |
| 5285 |
result = 37 * result + hql.hashCode(); |
|
| 5291 |
result = 37 * result + fql.hashCode(); |
|
| 5292 |
result = 37 * result + dialect.hashCode(); |
|
| 5286 | 5293 |
result = 37 * result + (hasMaxResults ? 1 : 0) + (hasStartOffset ? 2 : 0); |
| 5287 | 5294 |
result = 37 * result + whereStr.hashCode(); |
| 5288 | 5295 |
result = 37 * result + (lazyMode ? 1 : 0); |
| ... | ... | |
| 5308 | 5315 |
QueryKey that = (QueryKey) o; |
| 5309 | 5316 |
|
| 5310 | 5317 |
return this.hash == that.hash && |
| 5318 |
this.dialect.equals(that.dialect) && |
|
| 5311 | 5319 |
this.hasMaxResults == that.hasMaxResults && |
| 5312 | 5320 |
this.hasStartOffset == that.hasStartOffset && |
| 5313 | 5321 |
this.fql.equals(that.fql) && |
| ... | ... | |
| 5334 | 5342 |
@Override |
| 5335 | 5343 |
public String toString() |
| 5336 | 5344 |
{
|
| 5337 |
return fql + "[" + hasMaxResults + ":" + hasStartOffset + "];" + whereStr;
|
|
| 5345 |
return fql + "[" + hasMaxResults + ":" + hasStartOffset + "] (" + dialect + ") " + whereStr;
|
|
| 5338 | 5346 |
} |
| 5339 | 5347 |
} |
| 5340 | 5348 |
|
| ... | ... | |
| 5561 | 5569 |
Query query = null; |
| 5562 | 5570 |
fql = fql.trim(); // just in case |
| 5563 | 5571 |
|
| 5564 |
// TODO: use the dialect also? I.e: is it possible to have different SQL for same FQL |
|
| 5565 |
// if different dialects are used? |
|
| 5566 |
QueryKey key = new QueryKey(fql, maxResults, startOffset, relation, lazyMode); |
|
| 5572 |
QueryKey key = new QueryKey(fql, dialect, maxResults, startOffset, relation, lazyMode); |
|
| 5567 | 5573 |
|
| 5568 |
synchronized (staticQueryCache) |
|
| 5574 |
query = staticQueryCache.get(key); |
|
| 5575 |
if (query == null) |
|
| 5569 | 5576 |
{
|
| 5570 |
query = staticQueryCache.get(key); |
|
| 5571 |
if (query == null) |
|
| 5577 |
Consumer<Query> c = (q) -> |
|
| 5572 | 5578 |
{
|
| 5573 |
query = Session.createQuery(q -> |
|
| 5574 |
{
|
|
| 5575 |
synchronized (staticQueryCache) |
|
| 5576 |
{
|
|
| 5577 |
// NOTE: the FQL string is not converted to SQL at this time. The conversion |
|
| 5578 |
// is performed once, lazily, when the first navigation is required by a |
|
| 5579 |
// call of list(), scroll(), or uniqueResult() on the new query |
|
| 5580 |
|
|
| 5581 |
staticQueryCache.put(key, q); |
|
| 5582 |
} |
|
| 5583 |
}, |
|
| 5584 |
fql); |
|
| 5585 |
} |
|
| 5579 |
// NOTE: the FQL string is not converted to SQL at this time. The conversion |
|
| 5580 |
// is performed once, lazily, when the first navigation is required by a |
|
| 5581 |
// call of list(), scroll(), or uniqueResult() on the new query |
|
| 5582 |
|
|
| 5583 |
staticQueryCache.put(key, q); |
|
| 5584 |
}; |
|
| 5585 |
|
|
| 5586 |
query = Session.createQuery(c, fql); |
|
| 5586 | 5587 |
} |
| 5587 | 5588 |
|
| 5588 | 5589 |
// update [maxResults] and [startOffset] because the cached query might have set |
| ... | ... | |
| 5979 | 5980 |
try |
| 5980 | 5981 |
{
|
| 5981 | 5982 |
session.associate(record); |
| 5983 |
record.refreshHydrator(session); |
|
| 5982 | 5984 |
} |
| 5983 | 5985 |
catch (StaleRecordException exc) |
| 5984 | 5986 |
{
|
| ... | ... | |
| 6142 | 6144 |
try |
| 6143 | 6145 |
{
|
| 6144 | 6146 |
closingSession = true; |
| 6145 |
|
|
| 6147 |
hydrateActiveRecords(); |
|
| 6146 | 6148 |
if (isTransactionOpen()) |
| 6147 | 6149 |
{
|
| 6148 | 6150 |
if (LOG.isLoggable(Level.WARNING)) |
| ... | ... | |
| 6221 | 6223 |
} |
| 6222 | 6224 |
} |
| 6223 | 6225 |
|
| 6226 |
private void hydrateActiveRecords() |
|
| 6227 |
{
|
|
| 6228 |
Iterator<RecordBuffer> iter = bufferManager.activeBuffers(Persistence.this); |
|
| 6229 |
|
|
| 6230 |
Record record; |
|
| 6231 |
|
|
| 6232 |
while (iter.hasNext()) |
|
| 6233 |
{
|
|
| 6234 |
record = iter.next().getCurrentRecord(); |
|
| 6235 |
if (record.primaryKey() < 0) |
|
| 6236 |
{
|
|
| 6237 |
continue; |
|
| 6238 |
} |
|
| 6239 |
|
|
| 6240 |
record.hydrateRemainingFields(); |
|
| 6241 |
} |
|
| 6242 |
} |
|
| 6243 |
|
|
| 6224 | 6244 |
/** |
| 6225 | 6245 |
* Notify all registered session listeners that the current ORM session is about to |
| 6226 | 6246 |
* close or the current, implicit transaction is being committed. Listeners which were set |
| new/src/com/goldencode/p2j/persist/Record.java 2026-05-22 13:59:11 +0000 | ||
|---|---|---|
| 2 | 2 |
** Module : Record.java |
| 3 | 3 |
** Abstract : The abstract base class for all business data model object classes. |
| 4 | 4 |
** |
| 5 |
** Copyright (c) 2019-2026, Golden Code Development Corporation.
|
|
| 5 |
** Copyright (c) 2019-2025, Golden Code Development Corporation.
|
|
| 6 | 6 |
** |
| 7 | 7 |
** -#- -I- --Date-- ---------------------------------------Description--------------------------------------- |
| 8 | 8 |
** 001 ECF 20191001 Created initial version with basic data and accessors. |
| ... | ... | |
| 35 | 35 |
** 012 AI 20250625 Added overload of getPropertyValues(boolean). |
| 36 | 36 |
** 013 LS 20250523 Changed getPropertyValues() to set the key of the map in a more consistent way for |
| 37 | 37 |
** denormalized extents. |
| 38 |
** 014 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 39 | 38 |
*/ |
| 40 | 39 | |
| 41 | 40 |
/* |
| ... | ... | |
| 102 | 101 |
import java.util.*; |
| 103 | 102 |
import java.util.function.*; |
| 104 | 103 | |
| 104 |
import com.goldencode.p2j.jmx.*; |
|
| 105 | 105 |
import com.goldencode.p2j.oo.lang.BaseObject; |
| 106 | 106 |
import com.goldencode.p2j.persist.orm.*; |
| 107 | 107 |
import com.goldencode.p2j.util.*; |
| ... | ... | |
| 115 | 115 |
extends BaseRecord |
| 116 | 116 |
implements PropertiesDescriptor |
| 117 | 117 |
{
|
| 118 |
private static final SimpleCounter HYDRATE_RECORDS_WHEN_SESSION_CLOSE = |
|
| 119 |
SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedRecordsWhenSessionCloses); |
|
| 120 |
|
|
| 121 |
private static final SimpleCounter TOTAL_FIELDS = |
|
| 122 |
SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentTotalFields); |
|
| 123 |
|
|
| 124 |
private static final SimpleCounter HYDRATE_FIELD_WHEN_SESSION_CLOSES = |
|
| 125 |
SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedFieldsWhenSessionCloses); |
|
| 126 | ||
| 127 |
private static final SimpleCounter HYDRATED_FIELDS_LZS = |
|
| 128 |
SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedFieldsWithLZS); |
|
| 129 |
|
|
| 130 |
private static final SimpleCounter HYDRATED_FIELDS_LOADER = |
|
| 131 |
SimpleCounter.getInstance(FwdServerJMX.Counter.PersistentHydratedFieldsWithLoader); |
|
| 132 |
|
|
| 118 | 133 |
/** |
| 119 | 134 |
* Default constructor needed by DMOs extending this class. |
| 120 | 135 |
*/ |
| ... | ... | |
| 163 | 178 |
{
|
| 164 | 179 |
checkIncomplete(offset); |
| 165 | 180 | |
| 166 |
Integer datum = (Integer) data[offset];
|
|
| 181 |
Integer datum = (Integer) getDatum(offset);
|
|
| 167 | 182 |
|
| 168 | 183 |
return datum != null ? new integer(datum) : new integer(); |
| 169 | 184 |
} |
| ... | ... | |
| 272 | 287 |
{
|
| 273 | 288 |
checkIncomplete(offset); |
| 274 | 289 | |
| 275 |
OffsetDateTime datum = (OffsetDateTime) data[offset];
|
|
| 290 |
OffsetDateTime datum = (OffsetDateTime) getDatum(offset);
|
|
| 276 | 291 |
|
| 277 | 292 |
return datum != null ? new datetimetz(datum) : new datetimetz(); |
| 278 | 293 |
} |
| ... | ... | |
| 362 | 377 |
} |
| 363 | 378 |
} |
| 364 | 379 |
|
| 380 |
@Override |
|
| 381 |
protected void countHydrateRecordWhenSessionCloses(long count) |
|
| 382 |
{
|
|
| 383 |
HYDRATE_RECORDS_WHEN_SESSION_CLOSE.update(count); |
|
| 384 |
} |
|
| 385 |
|
|
| 386 |
@Override |
|
| 387 |
protected void countTotalFields(long count) |
|
| 388 |
{
|
|
| 389 |
TOTAL_FIELDS.update(count); |
|
| 390 |
} |
|
| 391 |
|
|
| 392 |
@Override |
|
| 393 |
protected void countHydratedFieldsWithLoader(long count) |
|
| 394 |
{
|
|
| 395 |
HYDRATED_FIELDS_LOADER.update(count); |
|
| 396 |
} |
|
| 397 |
|
|
| 398 |
@Override |
|
| 399 |
protected void countHydratedFieldsWithLZS(long count) |
|
| 400 |
{
|
|
| 401 |
HYDRATED_FIELDS_LZS.update(count); |
|
| 402 |
} |
|
| 403 |
|
|
| 404 |
@Override |
|
| 405 |
protected void countHydratedFieldWhenSessionCloses(long count) |
|
| 406 |
{
|
|
| 407 |
HYDRATE_FIELD_WHEN_SESSION_CLOSES.update(count); |
|
| 408 |
} |
|
| 409 |
|
|
| 365 | 410 |
/** |
| 366 | 411 |
* Get an {@code datetime} value for the datum at the given offset in the property array.
|
| 367 | 412 |
* <p> |
| ... | ... | |
| 378 | 423 |
{
|
| 379 | 424 |
checkIncomplete(offset); |
| 380 | 425 | |
| 381 |
Timestamp datum = (Timestamp) data[offset];
|
|
| 426 |
Timestamp datum = (Timestamp) getDatum(offset);
|
|
| 382 | 427 |
|
| 383 | 428 |
return datum != null ? new datetime(datum) : new datetime(); |
| 384 | 429 |
} |
| ... | ... | |
| 483 | 528 |
{
|
| 484 | 529 |
checkIncomplete(offset); |
| 485 | 530 | |
| 486 |
Date datum = (Date) data[offset];
|
|
| 531 |
Date datum = (Date) getDatum(offset);
|
|
| 487 | 532 |
|
| 488 | 533 |
return datum != null ? new date(datum) : new date(); |
| 489 | 534 |
} |
| ... | ... | |
| 588 | 633 |
{
|
| 589 | 634 |
checkIncomplete(offset); |
| 590 | 635 | |
| 591 |
Boolean datum = (Boolean) data[offset];
|
|
| 636 |
Boolean datum = (Boolean) getDatum(offset);
|
|
| 592 | 637 |
|
| 593 | 638 |
return datum != null ? new logical(datum) : new logical(); |
| 594 | 639 |
} |
| ... | ... | |
| 691 | 736 |
*/ |
| 692 | 737 |
public final int64 _getInt64(int offset) |
| 693 | 738 |
{
|
| 694 |
Long datum = (Long) data[offset]; |
|
| 739 |
checkIncomplete(offset); |
|
| 740 |
|
|
| 741 |
Long datum = (Long) getDatum(offset); |
|
| 695 | 742 |
|
| 696 | 743 |
return datum != null ? new int64(datum) : new int64(); |
| 697 | 744 |
} |
| ... | ... | |
| 800 | 847 |
{
|
| 801 | 848 |
checkIncomplete(offset); |
| 802 | 849 | |
| 803 |
BigDecimal datum = (BigDecimal) data[offset];
|
|
| 850 |
BigDecimal datum = (BigDecimal) getDatum(offset);
|
|
| 804 | 851 |
|
| 805 | 852 |
return datum != null ? new decimal(datum) : new decimal(); |
| 806 | 853 |
} |
| ... | ... | |
| 917 | 964 |
public final character _getCharacter(int offset) |
| 918 | 965 |
{
|
| 919 | 966 |
checkIncomplete(offset); |
| 920 | ||
| 921 |
String datum = (String) data[offset];
|
|
| 967 |
|
|
| 968 |
String datum = (String) getDatum(offset);
|
|
| 922 | 969 |
|
| 923 | 970 |
if (datum != null) |
| 924 | 971 |
{
|
| ... | ... | |
| 1030 | 1077 |
{
|
| 1031 | 1078 |
checkIncomplete(offset); |
| 1032 | 1079 | |
| 1033 |
Long datum = (Long) data[offset];
|
|
| 1080 |
Long datum = (Long) getDatum(offset);
|
|
| 1034 | 1081 |
|
| 1035 | 1082 |
return datum != null ? new rowid(datum) : new rowid(); |
| 1036 | 1083 |
} |
| ... | ... | |
| 1137 | 1184 |
{
|
| 1138 | 1185 |
checkIncomplete(offset); |
| 1139 | 1186 | |
| 1140 |
Long datum = (Long) data[offset];
|
|
| 1187 |
Long datum = (Long) getDatum(offset);
|
|
| 1141 | 1188 |
|
| 1142 | 1189 |
return datum != null ? handle.fromResourceId(datum, false) : new handle(); |
| 1143 | 1190 |
} |
| ... | ... | |
| 1244 | 1291 |
{
|
| 1245 | 1292 |
checkIncomplete(offset); |
| 1246 | 1293 | |
| 1247 |
Long datum = (Long) data[offset];
|
|
| 1294 |
Integer datum = (Integer) getDatum(offset);
|
|
| 1248 | 1295 |
|
| 1249 | 1296 |
return datum != null ? new recid(datum) : new recid(); |
| 1250 | 1297 |
} |
| ... | ... | |
| 1263 | 1310 |
*/ |
| 1264 | 1311 |
protected final void _setRecid(int offset, NumberType w) |
| 1265 | 1312 |
{
|
| 1266 |
Long datum = null;
|
|
| 1313 |
Integer datum = null;
|
|
| 1267 | 1314 |
if (w != null && !w.isUnknown()) |
| 1268 | 1315 |
{
|
| 1269 |
datum = w.longValue();
|
|
| 1316 |
datum = w.intValue();
|
|
| 1270 | 1317 |
} |
| 1271 | 1318 |
|
| 1272 | 1319 |
setDatum(offset, datum); |
| ... | ... | |
| 1350 | 1397 |
{
|
| 1351 | 1398 |
checkIncomplete(offset); |
| 1352 | 1399 | |
| 1353 |
byte[] datum = (byte[]) data[offset];
|
|
| 1400 |
byte[] datum = (byte[]) getDatum(offset);
|
|
| 1354 | 1401 |
|
| 1355 | 1402 |
return datum != null ? new blob(datum) : new blob(); |
| 1356 | 1403 |
} |
| ... | ... | |
| 1457 | 1504 |
{
|
| 1458 | 1505 |
checkIncomplete(offset); |
| 1459 | 1506 | |
| 1460 |
return new clob((String) data[offset], getCodePage(offset));
|
|
| 1507 |
return new clob((String) getDatum(offset), getCodePage(offset));
|
|
| 1461 | 1508 |
} |
| 1462 | 1509 |
|
| 1463 | 1510 |
/** |
| ... | ... | |
| 1560 | 1607 |
{
|
| 1561 | 1608 |
checkIncomplete(offset); |
| 1562 | 1609 | |
| 1563 |
String datum = (String) data[offset];
|
|
| 1610 |
String datum = (String) getDatum(offset);
|
|
| 1564 | 1611 |
|
| 1565 | 1612 |
return datum != null ? comhandle.fromString(datum) : new comhandle(); |
| 1566 | 1613 |
} |
| ... | ... | |
| 1665 | 1712 |
{
|
| 1666 | 1713 |
checkIncomplete(offset); |
| 1667 | 1714 | |
| 1668 |
Long datum = (Long) data[offset];
|
|
| 1715 |
Long datum = (Long) getDatum(offset);
|
|
| 1669 | 1716 |
|
| 1670 | 1717 |
// the instance must be typed to Progress.Lang.Object |
| 1671 | 1718 |
object<?> res = new object<>(BaseObject.class); |
| ... | ... | |
| 1781 | 1828 |
{
|
| 1782 | 1829 |
checkIncomplete(offset); |
| 1783 | 1830 | |
| 1784 |
byte[] datum = (byte[]) data[offset];
|
|
| 1831 |
byte[] datum = (byte[]) getDatum(offset);
|
|
| 1785 | 1832 |
|
| 1786 | 1833 |
return datum != null ? new raw(datum) : raw.instantiateUnknownRaw(); |
| 1787 | 1834 |
} |
| ... | ... | |
| 1956 | 2003 |
RecordMeta meta = _recordMeta(); |
| 1957 | 2004 |
if (oneLine) |
| 1958 | 2005 |
{
|
| 1959 |
int last = data.length;
|
|
| 2006 |
int last = getLength();
|
|
| 1960 | 2007 |
int start = (this instanceof TempTableRecord) ? 5 : 0; |
| 1961 | 2008 |
sb.append(meta.legacyName).append('/').append(meta.tables[0]).append(':').append(id).append(" {");
|
| 1962 | 2009 |
for (int i = start; i < last; i++) |
| ... | ... | |
| 1966 | 2013 |
sb.append(", ");
|
| 1967 | 2014 |
} |
| 1968 | 2015 |
|
| 1969 |
boolean isChar = data[i] instanceof String;
|
|
| 2016 |
boolean isChar = getSimpleDatum(i) instanceof String;
|
|
| 1970 | 2017 |
if (isChar) |
| 1971 | 2018 |
{
|
| 1972 | 2019 |
sb.append("\"");
|
| ... | ... | |
| 1974 | 2021 |
|
| 1975 | 2022 |
boolean incomplete = readFields != null && !readFields.get(i); |
| 1976 | 2023 |
|
| 1977 |
sb.append(data[i] == null ? incomplete ? "n/a" : "?" : data[i]); |
|
| 2024 |
Object datum = getSimpleDatum(i); |
|
| 2025 |
sb.append(datum == null ? incomplete ? "n/a" : "?" : datum); |
|
| 1978 | 2026 |
if (isChar) |
| 1979 | 2027 |
{
|
| 1980 | 2028 |
sb.append("\"");
|
| ... | ... | |
| 1997 | 2045 |
int extent = pms[i].getExtent(); |
| 1998 | 2046 |
if (extent == 0) |
| 1999 | 2047 |
{
|
| 2000 |
sb.append(data[i]);
|
|
| 2048 |
sb.append(getSimpleDatum(i));
|
|
| 2001 | 2049 |
} |
| 2002 | 2050 |
else |
| 2003 | 2051 |
{
|
| 2004 | 2052 |
for (int k = 0; k < extent; k++) |
| 2005 | 2053 |
{
|
| 2006 | 2054 |
sb.append(k == 0 ? "[" : ""); |
| 2007 |
sb.append(data[i + k]);
|
|
| 2055 |
sb.append(getSimpleDatum(i + k));
|
|
| 2008 | 2056 |
} |
| 2009 | 2057 |
|
| 2010 | 2058 |
i += extent - 1; |
| ... | ... | |
| 2042 | 2090 |
Object val = properties.get(prop.getLegacyName()); |
| 2043 | 2091 |
val = f.apply(prop, val); |
| 2044 | 2092 | |
| 2093 |
Object[] data = getData(); |
|
| 2045 | 2094 |
if (prop.getExtent() > 0) |
| 2046 | 2095 |
{
|
| 2047 | 2096 |
for (int j = 0; j < prop.getExtent(); j++, i++) |
| ... | ... | |
| 2050 | 2099 |
|
| 2051 | 2100 |
BaseDataType fval = (BaseDataType) Array.get(val, j); |
| 2052 | 2101 |
prop.getDataHandler().setField(data, fval, i, prop); |
| 2102 |
setLivePropsAtOffset(i); |
|
| 2053 | 2103 |
} |
| 2054 | 2104 |
} |
| 2055 | 2105 |
else |
| 2056 | 2106 |
{
|
| 2057 | 2107 |
prop.getDataHandler().setField(data, (BaseDataType) val, i, prop); |
| 2108 |
setLivePropsAtOffset(i); |
|
| 2058 | 2109 |
} |
| 2059 | 2110 |
} |
| 2060 | 2111 |
} |
| ... | ... | |
| 2127 | 2178 |
} |
| 2128 | 2179 |
|
| 2129 | 2180 |
/** |
| 2130 |
* Check if two {@link Record} objects are equal from the point of view of the {@code data} array.
|
|
| 2131 |
* <p> |
|
| 2132 |
* <strong>To be noted</strong>, that this method accesses the {@code data} arrays directly without using
|
|
| 2133 |
* any getter. This provides faster access, however should be changed if not all fields are hydrated and |
|
| 2134 |
* access is mandatory from a getter. |
|
| 2135 |
* |
|
| 2136 |
* @param otherRecord |
|
| 2137 |
* The instance to compare against. |
|
| 2138 |
* |
|
| 2139 |
* @return True if the {@code data} arrays are equal, false - otherwise
|
|
| 2140 |
*/ |
|
| 2141 |
public boolean equalData(Record otherRecord) |
|
| 2142 |
{
|
|
| 2143 |
return Arrays.equals(this.data, otherRecord.data); |
|
| 2144 |
} |
|
| 2145 |
|
|
| 2146 |
/** |
|
| 2147 | 2181 |
* Converts this {@code Record} into a POJO, if POJO class is available.
|
| 2148 | 2182 |
* To be implemented by DMO implementations. |
| 2149 | 2183 |
* |
| new/src/com/goldencode/p2j/persist/RecordBuffer.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 1437 | 1437 |
** 412 SP 20251029 Refactor propsMap to use destination as key and source as value. |
| 1438 | 1438 |
** 413 TG 20250925 Avoid openScope call for the same buffer in the current scope. |
| 1439 | 1439 |
** 414 RNC 20251118 Log DirectAccessException in 'setCurrentRecord()' only if it is not expected. |
| 1440 |
** 415 AS 20251210 When -rereadfields is active, fully hydrate a record instaead of throwing 8826 error. |
|
| 1441 |
** 416 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 1440 |
** 415 AS 20251210 When -rereadfields is active, fully hydrate a record instaead of throwing 8826 error. |
|
| 1442 | 1441 |
*/ |
| 1443 | 1442 | |
| 1444 | 1443 |
/* |
| ... | ... | |
| 7181 | 7180 |
* Get the record ID of the current buffer's current record, if any. P2J |
| 7182 | 7181 |
* implementation of the RECID function. |
| 7183 | 7182 |
* <p> |
| 7184 |
* This method will return a 64-bit recid which represents the internal |
|
| 7185 |
* row ID of the given record. |
|
| 7183 |
* This method will return a 32-bit recid which represents the internal |
|
| 7184 |
* row ID of the given record. If the actual row ID (which is implemented |
|
| 7185 |
* as a wider integer) cannot fit due to overflow, an error condition will |
|
| 7186 |
* be raised. |
|
| 7186 | 7187 |
* |
| 7187 | 7188 |
* @return Record ID of the underlying data record. If no record currently |
| 7188 | 7189 |
* backs the buffer associated with <code>dmo</code>, a recid |
| 7189 | 7190 |
* initialized as unknown value is returned. |
| 7191 |
* |
|
| 7192 |
* @throws ErrorConditionException |
|
| 7193 |
* if the actual record ID is too wide to fit within a 32-bit |
|
| 7194 |
* integer. |
|
| 7190 | 7195 |
*/ |
| 7191 | 7196 |
public recid recordID() |
| 7192 | 7197 |
{
|
| 7193 |
return isAvailable() ? new recid(getCurrentRecord().primaryKey()) : new recid(); |
|
| 7198 |
if (isAvailable()) |
|
| 7199 |
{
|
|
| 7200 |
Record record = getCurrentRecord(); |
|
| 7201 |
long id = record.primaryKey(); |
|
| 7202 |
if (id < Integer.MIN_VALUE || id > Integer.MAX_VALUE) |
|
| 7203 |
{
|
|
| 7204 |
// TODO: don't know what 4GL's overflow behavior is or whether the corresponding |
|
| 7205 |
// error is more serious than an ERROR condition; internally, we support a 64-bit |
|
| 7206 |
// value, but the recid object follows the 32-bit constraint in terms of not |
|
| 7207 |
// formatting this |
|
| 7208 |
txHelper.errHlp.noRecordOrThrowError( |
|
| 7209 |
"Row id of " + id + " is too wide to fit within a 32-bit record ID"); |
|
| 7210 |
} |
|
| 7211 |
|
|
| 7212 |
return new recid(id); |
|
| 7213 |
} |
|
| 7214 |
else |
|
| 7215 |
{
|
|
| 7216 |
return new recid(); |
|
| 7217 |
} |
|
| 7194 | 7218 |
} |
| 7195 | 7219 |
|
| 7196 | 7220 |
/** |
| new/src/com/goldencode/p2j/persist/TempRecord.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 17 | 17 |
** 004 CA 20240918 Removed default methods from interfaces and moved them as concrete implementations, as |
| 18 | 18 |
** default methods cause the Java metaspace to spike one order of magnitude. |
| 19 | 19 |
** 005 AS 20241009 Refactored activeOffset into activeOffsets(Bitset). |
| 20 |
** 006 AL2 20231102 Added computeIndexForHydrator for lazy hydration. |
|
| 20 | 21 |
*/ |
| 21 | 22 | |
| 22 | 23 |
/* |
| ... | ... | |
| 74 | 75 | |
| 75 | 76 |
package com.goldencode.p2j.persist; |
| 76 | 77 | |
| 78 |
import com.goldencode.p2j.jmx.*; |
|
| 77 | 79 |
import com.goldencode.p2j.persist.orm.*; |
| 78 | 80 |
import com.goldencode.p2j.util.object; |
| 79 | 81 | |
| ... | ... | |
| 87 | 89 |
extends Record |
| 88 | 90 |
implements TempTableRecord |
| 89 | 91 |
{
|
| 92 |
private static final SimpleCounter HYDRATE_RECORDS_WHEN_SESSION_CLOSE = |
|
| 93 |
SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedRecordsWhenSessionCloses); |
|
| 94 |
|
|
| 95 |
private static final SimpleCounter TOTAL_FIELDS = |
|
| 96 |
SimpleCounter.getInstance(FwdServerJMX.Counter.TempTotalFields); |
|
| 97 |
|
|
| 98 |
private static final SimpleCounter HYDRATE_FIELD_WHEN_SESSION_CLOSES = |
|
| 99 |
SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedFieldsWhenSessionCloses); |
|
| 100 |
|
|
| 101 |
private static final SimpleCounter HYDRATED_FIELDS_LZS = |
|
| 102 |
SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedFieldsWithLZS); |
|
| 103 |
|
|
| 104 |
private static final SimpleCounter HYDRATED_FIELDS_LOADER = |
|
| 105 |
SimpleCounter.getInstance(FwdServerJMX.Counter.TempHydratedFieldsWithLoader); |
|
| 106 |
|
|
| 90 | 107 |
/** The property/column name of "__error-flag__" field. */ |
| 91 | 108 |
public static final String _ERROR_FLAG = "_errorFlag"; |
| 92 | 109 |
|
| ... | ... | |
| 197 | 214 |
@Override |
| 198 | 215 |
public final Long _peerRowid() |
| 199 | 216 |
{
|
| 200 |
return (Long) data[_PEER_ROWID_DATA_INDEX];
|
|
| 217 |
return (Long) getDatum(_PEER_ROWID_DATA_INDEX);
|
|
| 201 | 218 |
} |
| 202 | 219 |
|
| 203 | 220 |
/** |
| ... | ... | |
| 237 | 254 |
@Override |
| 238 | 255 |
public final Integer _rowState() |
| 239 | 256 |
{
|
| 240 |
return (Integer) data[_ROW_STATE_DATA_INDEX];
|
|
| 257 |
return (Integer) getDatum(_ROW_STATE_DATA_INDEX);
|
|
| 241 | 258 |
} |
| 242 | 259 |
|
| 243 | 260 |
/** |
| ... | ... | |
| 278 | 295 |
@Override |
| 279 | 296 |
public final Long _originRowid() |
| 280 | 297 |
{
|
| 281 |
return (Long) data[_ORIGIN_ROWID_DATA_INDEX];
|
|
| 298 |
return (Long) getDatum(_ORIGIN_ROWID_DATA_INDEX);
|
|
| 282 | 299 |
} |
| 283 | 300 |
|
| 284 | 301 |
/** |
| ... | ... | |
| 318 | 335 |
@Override |
| 319 | 336 |
public final Long _datasourceRowid() |
| 320 | 337 |
{
|
| 321 |
return (Long) data[_DATASOURCE_ROWID_INDEX];
|
|
| 338 |
return (Long) getDatum(_DATASOURCE_ROWID_INDEX);
|
|
| 322 | 339 |
} |
| 323 | 340 |
|
| 324 | 341 |
/** |
| ... | ... | |
| 356 | 373 |
@Override |
| 357 | 374 |
public final Integer _errorFlags() |
| 358 | 375 |
{
|
| 359 |
return (Integer) data[_ERROR_FLAG_DATA_INDEX];
|
|
| 376 |
return (Integer) getDatum(_ERROR_FLAG_DATA_INDEX);
|
|
| 360 | 377 |
} |
| 361 | 378 |
|
| 362 | 379 |
/** |
| ... | ... | |
| 392 | 409 |
@Override |
| 393 | 410 |
public final String _errorString() |
| 394 | 411 |
{
|
| 395 |
return (String) data[_ERROR_STRING_DATA_INDEX];
|
|
| 412 |
return (String) getDatum(_ERROR_STRING_DATA_INDEX);
|
|
| 396 | 413 |
} |
| 397 | 414 |
|
| 398 | 415 |
/** |
| ... | ... | |
| 507 | 524 |
Class<?> implIFace = _recordMeta().getDmoMeta().getAnnotatedInterface(); |
| 508 | 525 |
TemporaryBuffer.updateObjectRefCount(implIFace, oldVal, newVal); |
| 509 | 526 |
} |
| 527 |
|
|
| 528 |
@Override |
|
| 529 |
protected int getHydratorRowOffset() |
|
| 530 |
{
|
|
| 531 |
return 2; |
|
| 532 |
} |
|
| 533 |
|
|
| 534 |
@Override |
|
| 535 |
protected void countHydrateRecordWhenSessionCloses(long count) |
|
| 536 |
{
|
|
| 537 |
HYDRATE_RECORDS_WHEN_SESSION_CLOSE.update(count); |
|
| 538 |
} |
|
| 539 |
|
|
| 540 |
@Override |
|
| 541 |
protected void countTotalFields(long count) |
|
| 542 |
{
|
|
| 543 |
TOTAL_FIELDS.update(count); |
|
| 544 |
} |
|
| 545 |
|
|
| 546 |
@Override |
|
| 547 |
protected void countHydratedFieldsWithLZS(long count) |
|
| 548 |
{
|
|
| 549 |
HYDRATED_FIELDS_LZS.update(count); |
|
| 550 |
} |
|
| 551 |
|
|
| 552 |
@Override |
|
| 553 |
protected void countHydratedFieldsWithLoader(long count) |
|
| 554 |
{
|
|
| 555 |
HYDRATED_FIELDS_LOADER.update(count); |
|
| 556 |
} |
|
| 557 |
|
|
| 558 |
@Override |
|
| 559 |
protected void countHydratedFieldWhenSessionCloses(long count) |
|
| 560 |
{
|
|
| 561 |
HYDRATE_FIELD_WHEN_SESSION_CLOSES.update(count); |
|
| 562 |
} |
|
| 510 | 563 |
} |
| new/src/com/goldencode/p2j/persist/dialect/Dialect.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 605 | 605 |
} |
| 606 | 606 |
|
| 607 | 607 |
/** |
| 608 |
* Create the error descriptor from the SQLException message.
|
|
| 609 |
* |
|
| 608 |
* Create the error descriptor from the {@code SQLException} message.
|
|
| 609 |
*
|
|
| 610 | 610 |
* @param message |
| 611 | 611 |
* The SQLException message. |
| 612 | 612 |
* |
| ... | ... | |
| 620 | 620 |
/** |
| 621 | 621 |
* Check if Common Table Expressions should be used for converted CONTAINS operator |
| 622 | 622 |
* |
| 623 |
* @return <code>true</code> if Common Table Expressions should be used for converted CONTAINS operator |
|
| 623 |
* @return <code>true</code> if Common Table Expressions should be used for converted CONTAINS operator
|
|
| 624 | 624 |
*/ |
| 625 | 625 |
public boolean useCTE4Contains() |
| 626 | 626 |
{
|
| ... | ... | |
| 718 | 718 |
public abstract void generateWordTablesDDLImpl(String dbName, |
| 719 | 719 |
PrintStream out, |
| 720 | 720 |
String eoln, |
| 721 |
Collection<WordTable> wordTables);
|
|
| 721 |
Collection<WordTable> wordTables); |
|
| 722 | 722 |
|
| 723 | 723 |
/** |
| 724 | 724 |
* Create a data object, the purpose of which is specific to a particular |
| ... | ... | |
| 2189 | 2189 |
{
|
| 2190 | 2190 |
return null; |
| 2191 | 2191 |
} |
| 2192 | ||
| 2193 |
/** |
|
| 2194 |
* Indicate whether this dialect is likely to benefit from lazy hydration of DMOs when reading a record |
|
| 2195 |
* from the database. This serves as a hint, but may be overridden by configuration or runtime conditions. |
|
| 2196 |
* |
|
| 2197 |
* @return {@code true} unless overridden by subclasses.
|
|
| 2198 |
*/ |
|
| 2199 |
public boolean useLazyHydration() |
|
| 2200 |
{
|
|
| 2201 |
return true; |
|
| 2202 |
} |
|
| 2192 | 2203 |
|
| 2193 | 2204 |
/** |
| 2194 | 2205 |
* Use the provided database connection to extract the collation used by the database and report it |
| new/src/com/goldencode/p2j/persist/dialect/H2Helper.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 129 | 129 |
import com.goldencode.p2j.directory.*; |
| 130 | 130 |
import com.goldencode.p2j.persist.*; |
| 131 | 131 |
import com.goldencode.p2j.persist.Database; |
| 132 |
import com.goldencode.p2j.persist.dialect.*; |
|
| 132 | 133 |
import com.goldencode.p2j.persist.orm.*; |
| 133 | 134 |
import com.goldencode.p2j.persist.orm.Session; |
| 134 | 135 |
import com.goldencode.p2j.persist.pl.*; |
| new/src/com/goldencode/p2j/persist/dialect/P2JH2Dialect.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 145 | 145 |
** 054 OM 20250701 Multiple signatures changes in super class. |
| 146 | 146 |
** 055 OM 20250718 Added new method: isSequenceMissing(Throwable). |
| 147 | 147 |
** 056 OM 20250731 Dropped dead code related to old technology no longer in use. |
| 148 |
** ES 20250805 Inject computed __null column in orderBy clause. |
|
| 149 |
** 057 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 148 |
** ES 20250805 Inject computed __null column in orderBy clause. |
|
| 150 | 149 |
*/ |
| 151 | 150 | |
| 152 | 151 |
/* |
| ... | ... | |
| 258 | 257 |
{
|
| 259 | 258 |
fwd2sql.put("integer", "integer");
|
| 260 | 259 |
fwd2sql.put("Integer", "integer");
|
| 261 |
fwd2sql.put("recid", "bigint");
|
|
| 260 |
fwd2sql.put("recid", "integer");
|
|
| 262 | 261 |
fwd2sql.put("int64", "bigint");
|
| 263 | 262 |
fwd2sql.put("Long", "bigint");
|
| 264 | 263 |
fwd2sql.put("rowid", "bigint");
|
| new/src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 148 | 148 |
** 061 OM 20250718 Added new method: isSequenceMissing(Throwable). |
| 149 | 149 |
** 062 OM 20250731 Dropped dead code related to old technology no longer in use. |
| 150 | 150 |
** 063 OM 20250922 Simplified MSSQL indexes. |
| 151 |
** 064 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 152 | 151 |
*/ |
| 153 | 152 | |
| 154 | 153 |
/* |
| ... | ... | |
| 396 | 395 |
{
|
| 397 | 396 |
fwd2sql.put("integer", "int4");
|
| 398 | 397 |
fwd2sql.put("Integer", "int4");
|
| 399 |
fwd2sql.put("recid", "int8");
|
|
| 398 |
fwd2sql.put("recid", "int4");
|
|
| 400 | 399 |
fwd2sql.put("int64", "int8");
|
| 401 | 400 |
fwd2sql.put("Long", "int8");
|
| 402 | 401 |
fwd2sql.put("rowid", "int8");
|
| new/src/com/goldencode/p2j/persist/dialect/P2JSQLServer2012Dialect.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 33 | 33 |
** 013 ES 20250827 Make direction of the primary key to always use ascendent direction. |
| 34 | 34 |
** 014 OM 20250918 Droped NULL components from indexes. Added PK for unique indexes. |
| 35 | 35 |
** 015 RNC 20260127 Added SQLSERVER_LIKE_PATTERN_OPERATORS. |
| 36 |
** 016 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 37 | 36 |
*/ |
| 38 | 37 | |
| 39 | 38 |
/* |
| ... | ... | |
| 239 | 238 |
indexFieldSizes.put(integer.class, 4); // int |
| 240 | 239 |
indexFieldSizes.put(logical.class, 1); // bit |
| 241 | 240 |
indexFieldSizes.put(int64.class, 8); // bigint |
| 242 |
indexFieldSizes.put(recid.class, 8); // bigint
|
|
| 241 |
indexFieldSizes.put(recid.class, 4); // int
|
|
| 243 | 242 |
indexFieldSizes.put(datetimetz.class, 10); // datetimeoffset |
| 244 | 243 |
indexFieldSizes.put(datetime.class, 8); // datetime2 |
| 245 | 244 |
indexFieldSizes.put(date.class, 3); // date |
| ... | ... | |
| 253 | 252 |
|
| 254 | 253 |
fwd2sql.put("integer", "int");
|
| 255 | 254 |
fwd2sql.put("Integer", "int");
|
| 256 |
fwd2sql.put("recid", "bigint");
|
|
| 255 |
fwd2sql.put("recid", "int");
|
|
| 257 | 256 |
fwd2sql.put("int64", "bigint");
|
| 258 | 257 |
fwd2sql.put("Long", "bigint");
|
| 259 | 258 |
fwd2sql.put("rowid", "bigint");
|
| new/src/com/goldencode/p2j/persist/dirty/DefaultDirtyShareManager.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 834 | 834 |
indexUpdateStates.remove(ident); |
| 835 | 835 |
} |
| 836 | 836 |
|
| 837 |
String hql = "delete from " + entity + |
|
| 838 |
" where " + DatabaseManager.PRIMARY_KEY + " = ?"; |
|
| 837 |
String fql = "delete from " + entity + " where " + Session.PK + " = ?"; |
|
| 839 | 838 |
Session session = null; |
| 840 | 839 |
boolean inTx = false; |
| 841 | 840 |
|
| ... | ... | |
| 843 | 842 |
{
|
| 844 | 843 |
session = new Session(dirtyDatabase); |
| 845 | 844 |
inTx = session.beginTransaction(); |
| 846 |
Query query = Session.createQuery(hql);
|
|
| 845 |
Query query = Session.createQuery(fql);
|
|
| 847 | 846 |
query.setParameter(0, id); |
| 848 | 847 |
query.executeUpdate(session); |
| 849 | 848 |
session.commit(); |
| ... | ... | |
| 1223 | 1222 |
} |
| 1224 | 1223 |
|
| 1225 | 1224 |
/** |
| 1226 |
* Execute an HQL query and return the results as a list. If the query returns multiple results
|
|
| 1225 |
* Execute an FQL query and return the results as a list. If the query returns multiple results
|
|
| 1227 | 1226 |
* per row, each element in the list will be an array of {@code Object}s.
|
| 1228 | 1227 |
* <p> |
| 1229 | 1228 |
* No locking is attempted. |
| new/src/com/goldencode/p2j/persist/hql/DataTypeHelper.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 45 | 45 |
** 026 SP 20240516 Process the function name in getTypeFunction() when there is an underscore |
| 46 | 46 |
** 027 CA 20241107 Added character constant support. |
| 47 | 47 |
** 028 ICP 20250123 Added support for integer and int64 constants. |
| 48 |
** 029 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 49 | 48 |
*/ |
| 50 | 49 | |
| 51 | 50 |
/* |
| ... | ... | |
| 561 | 560 |
// P2J wrapper types. |
| 562 | 561 |
classes.put(logical.class , FqlType.BOOLEAN); |
| 563 | 562 |
classes.put(integer.class , FqlType.INTEGER); |
| 564 |
classes.put(recid.class , FqlType.LONG);
|
|
| 563 |
classes.put(recid.class , FqlType.INTEGER);
|
|
| 565 | 564 |
classes.put(decimal.class , FqlType.DECIMAL); |
| 566 | 565 |
classes.put(date.class , FqlType.DATE); |
| 567 | 566 |
classes.put(raw.class , FqlType.RAW); |
| new/src/com/goldencode/p2j/persist/meta/MetadataManager.java 2026-05-22 13:57:10 +0000 | ||
|---|---|---|
| 73 | 73 |
** 032 OM 20250331 Make sure the [byName] map's keys are in lowercase. Avoid possible duplication of default |
| 74 | 74 |
** tenant record in _tenant meta table. |
| 75 | 75 |
** 033 SP 20250321 Removed support for custom denormalized extents. |
| 76 |
** 034 RNC 20260401 Migrate RECID from 32-bit to 64-bit values. |
|
| 77 | 76 |
*/ |
| 78 | 77 | |
| 79 | 78 |
/* |
| ... | ... | |
| 215 | 214 |
private static final boolean LOG_INFO = log.isLoggable(Level.INFO); |
| 216 | 215 |
|
| 217 | 216 |
/** The recid of the database in {@code _Db} table. */
|
| 218 |
private static final long DB_RECID = 4032;
|
|
| 217 |
private static final int DB_RECID = 4032;
|
|
| 219 | 218 |
|
| 220 | 219 |
/** Map of data type names to associated _Field._dtype value */ |
| 221 | 220 |
private static final Map<String, Integer> DTYPE = Collections.unmodifiableMap( |
| ... | ... | |
| 252 | 251 |
put("logical", "bit");
|
| 253 | 252 |
put("integer", "integer");
|
| 254 | 253 |
put("decimal", "numetic");
|
| 255 |
put("recid", "bigint");
|
|
| 254 |
put("recid", "integer");
|
|
| 256 | 255 |
put("raw", "varbinary");
|
| 257 | 256 |
put("blob", "varbinary");
|
| 258 | 257 |
put("clob", "varchar");
|
| ... | ... | |
| 825 | 824 |
// extract the list of indices of this table ... |
| 826 | 825 |
PreparedStatement stmt = conn.prepareStatement( |
| 827 | 826 |
"select " + Session.PK + " from meta_index where file_recid=?"); |
| 828 |
stmt.setLong(1, fileNum2); |
|
| 827 |
stmt.setLong(1, (long) fileNum2);
|
|
| 829 | 828 |
ResultSet rs = stmt.executeQuery(); |
| 830 | 829 |
while (rs.next()) |
| 831 | 830 |
{
|
| 832 | 831 |
// ... and drop their index components |
| 833 |
deleteRecord(conn, |
|
| 834 |
rs.getLong(1), |
|
| 835 |
"delete from meta_index_field where index_recid=?", |
|
| 836 |
"index components"); |
|
| 832 |
deleteRecord( |
|
| 833 |
conn, rs.getInt(1), "delete from meta_index_field where index_recid=?", "index components"); |
|
| 837 | 834 |
} |
| 838 | 835 |
rs.close(); |
| 839 | 836 |
stmt.close(); |
| 840 | 837 |
|
| 841 | 838 |
// then, delete them from _Index |
| 842 |
deleteRecord(conn, fileNum2, "delete from meta_index where file_recid=?", "indices"); |
|
| 839 |
deleteRecord(conn, (long) fileNum2, "delete from meta_index where file_recid=?", "indices");
|
|
| 843 | 840 |
|
| 844 | 841 |
// next, delete from _Field |
| 845 |
deleteRecord(conn, fileNum2, "delete from meta_field where file_recid=?", "fields"); |
|
| 842 |
deleteRecord(conn, (long) fileNum2, "delete from meta_field where file_recid=?", "fields");
|
|
| 846 | 843 |
|
| 847 | 844 |
// finally, delete from _File |
| 848 |
deleteRecord(conn, fileNum2, "delete from meta_file where " + Session.PK + "=?", "tables"); |
|
| 845 |
deleteRecord(conn, (long) fileNum2, "delete from meta_file where " + Session.PK + "=?", "tables");
|
|
| 849 | 846 |
|
| 850 | 847 |
if (inTx) |
| 851 | 848 |
{
|
| ... | ... | |
| 999 | 996 |
} |
| 1000 | 997 |
|
| 1001 | 998 |
long fileNum = nextId(meta, SystemTable._File.fileName); |
| 1002 |
int64 pk = new int64();
|
|
| 999 |
integer pk = new integer();
|
|
| 1003 | 1000 |
Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children = |
| 1004 |
childData(meta, dmoIface, fileNum, pk); |
|
| 1001 |
childData(meta, dmoIface, (int)fileNum, pk);
|
|
| 1005 | 1002 |
setMetaTableRecord(p, fileHelper, |
| 1006 | 1003 |
new FileTableRecordBuilder() |
| 1007 | 1004 |
.put(Session.PK, fileNum) |
| 1008 | 1005 |
.put("fileNumber", integer.of(fileNum))
|
| 1009 |
.put("template", int64.of(-fileNum))
|
|
| 1006 |
.put("template", integer.of(-fileNum))
|
|
| 1010 | 1007 |
.put("tblType", character.of("T"))
|
| 1011 | 1008 |
.build(dmoIface, pk, children) |
| 1012 | 1009 |
); |
| 1013 | 1010 |
templateRecords.put(dmoImpl, -fileNum); |
| 1014 | 1011 |
FILE_NUM.computeIfAbsent(primary, d -> new ConcurrentHashMap<>()). |
| 1015 |
putIfAbsent(dmoImpl, integer.of((int) fileNum));
|
|
| 1012 |
putIfAbsent(dmoImpl, new integer(fileNum));
|
|
| 1016 | 1013 |
FILE_NUM_BY_TBL_NAME.computeIfAbsent(primary, d -> new ConcurrentHashMap<>()). |
| 1017 |
putIfAbsent(dmoIface.getAnnotation(Table.class).name(), (int) fileNum);
|
|
| 1014 |
putIfAbsent(dmoIface.getAnnotation(Table.class).name(), (int)fileNum); |
|
| 1018 | 1015 |
saveChildren(p, children); |
| 1019 | 1016 |
|
| 1020 | 1017 |
if ((isDynamic && LOG_INFO) || log.isLoggable(Level.FINE)) |
| ... | ... | |
| 1081 | 1078 |
return false; |
| 1082 | 1079 |
} |
| 1083 | 1080 |
|
| 1084 |
int64 pk = new int64();
|
|
| 1081 |
integer pk = new integer();
|
|
| 1085 | 1082 |
Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children = childData( |
| 1086 | 1083 |
metaDb, dmoIface, systemTable.fileNum, pk); |
| 1087 | 1084 |
long id = nextId(metaDb, SystemTable._File.fileName); |
| 1088 | ||
| 1085 |
|
|
| 1089 | 1086 |
setMetaTableRecord(p, fileHelper, |
| 1090 | 1087 |
new FileTableRecordBuilder() |
| 1091 | 1088 |
.put(Session.PK, id) |
| 1092 |
.put("fileNumber", integer.of(systemTable.fileNum))
|
|
| 1093 |
.put("template", int64.of(-id))
|
|
| 1089 |
.put("fileNumber", new integer(systemTable.fileNum))
|
|
| 1090 |
.put("template", new integer(-id))
|
|
| 1094 | 1091 |
.put("tblType", new character("S"))
|
| 1095 | 1092 |
.build(dmoIface, pk, children) |
| 1096 | 1093 |
); |
| ... | ... | |
| 1188 | 1185 |
new MapBuilder<>(). |
| 1189 | 1186 |
put(Session.PK, nextId). |
| 1190 | 1187 |
put("seqName", new character(seq.legacy())).
|
| 1191 |
put("seqInit", int64.of(seq.start())).
|
|
| 1192 |
put("seqIncr", int64.of(seq.increment())).
|
|
| 1193 |
put("seqMin", int64.of(seq.minValue())).
|
|
| 1194 |
put("seqMax",int64.of(seq.maxValue())).
|
|
| 1188 |
put("seqInit", new int64(seq.start())).
|
|
| 1189 |
put("seqIncr", new int64(seq.increment())).
|
|
| 1190 |
put("seqMin", new int64(seq.minValue())).
|
|
| 1191 |
put("seqMax",new int64(seq.maxValue())).
|
|
| 1195 | 1192 |
put("cycleOk",new logical(seq.cycle())).
|
| 1196 | 1193 |
put("dbRecid",new recid(nextId)).
|
| 1197 |
build()
|
|
| 1194 |
build() |
|
| 1198 | 1195 |
); |
| 1199 | 1196 |
} |
| 1200 | 1197 |
} catch (NoSuchMethodException | SecurityException | |
| ... | ... | |
| 1281 | 1278 |
|
| 1282 | 1279 |
setMetaTableRecord(p, h, |
| 1283 | 1280 |
new MapBuilder<>() |
| 1284 |
.put(Session.PK, DB_RECID) |
|
| 1281 |
.put(Session.PK, (long) DB_RECID)
|
|
| 1285 | 1282 |
.put("dbName", new character("_meta"))
|
| 1286 | 1283 |
.put("dbType", new character(""))
|
| 1287 | 1284 |
.put("dbComm", new character(""))
|
| ... | ... | |
| 1910 | 1907 |
private static Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> childData( |
| 1911 | 1908 |
Database metaDb, |
| 1912 | 1909 |
Class<? extends DataModelObject> dmoIface, |
| 1913 |
long _file_num,
|
|
| 1914 |
int64 pk)
|
|
| 1910 |
int _file_num,
|
|
| 1911 |
integer pk)
|
|
| 1915 | 1912 |
{
|
| 1916 | 1913 |
Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children = new EnumMap<>(SystemTable.class); |
| 1917 | 1914 |
List<Map<Tuple<String, Integer>, Object>> fields = new LinkedList<>(); |
| ... | ... | |
| 1919 | 1916 |
List<Map<Tuple<String, Integer>, Object>> indexFields = new LinkedList<>(); |
| 1920 | 1917 |
List<Map<Tuple<String, Integer>, Object>> fileTriggers = new LinkedList<>(); |
| 1921 | 1918 |
List<Map<Tuple<String, Integer>, Object>> fieldTriggers = new LinkedList<>(); |
| 1922 |
Map<String, int64> fieldRecidByName = new LinkedHashMap<>();
|
|
| 1919 |
Map<String, integer> fieldRecidByName = new LinkedHashMap<>();
|
|
| 1923 | 1920 |
Map<String, integer> fieldRposByName = new LinkedHashMap<>(); |
| 1924 | 1921 |
children.put(SystemTable._Field, fields); |
| 1925 | 1922 |
children.put(SystemTable._Index, indexes); |
| ... | ... | |
| 1946 | 1943 |
String field = trigger.field(); |
| 1947 | 1944 |
if (!field.isEmpty()) |
| 1948 | 1945 |
{
|
| 1949 |
int64 fieldRecId = fieldRecidByName.get(field);
|
|
| 1946 |
integer fieldRecId = fieldRecidByName.get(field);
|
|
| 1950 | 1947 |
integer fieldRpos = fieldRposByName.get(field); |
| 1951 | 1948 |
if (fieldRecId == null || fieldRpos == null) |
| 1952 | 1949 |
{
|
| ... | ... | |
| 1962 | 1959 |
new MapBuilder<>(). |
| 1963 | 1960 |
put(Session.PK, nextId(metaDb, SystemTable._Field_Trig.fileName)). |
| 1964 | 1961 |
put("fieldRecid", fieldRecId).
|
| 1965 |
put("fileRecid", int64.of(_file_num)).
|
|
| 1962 |
put("fileRecid", integer.of(_file_num)).
|
|
| 1966 | 1963 |
put("fieldRpos", fieldRpos).
|
| 1967 | 1964 |
put("event", new character(trigger.event())).
|
| 1968 | 1965 |
put("procName", new character(trigger.procedure())).
|
| ... | ... | |
| 1975 | 1972 |
fileTriggers.add( |
| 1976 | 1973 |
new MapBuilder<>(). |
| 1977 | 1974 |
put(Session.PK, nextId(metaDb, SystemTable._File_Trig.fileName)). |
| 1978 |
put("fileRecid", int64.of(_file_num)).
|
|
| 1975 |
put("fileRecid", integer.of(_file_num)).
|
|
| 1979 | 1976 |
put("event", new character(trigger.event())).
|
| 1980 | 1977 |
put("procName", new character(trigger.procedure())).
|
| 1981 | 1978 |
put("override", logical.of(trigger.overridable())).
|
| ... | ... | |
| 2008 | 2005 |
*/ |
| 2009 | 2006 |
private static void indexData(Database metaDb, |
| 2010 | 2007 |
String tblDmoName, |
| 2011 |
long _file_num,
|
|
| 2008 |
int _file_num,
|
|
| 2012 | 2009 |
Iterator<P2JIndex> indices, |
| 2013 |
int64 pk,
|
|
| 2010 |
integer pk,
|
|
| 2014 | 2011 |
List<Map<Tuple<String, Integer>, Object>> indexes, |
| 2015 | 2012 |
List<Map<Tuple<String, Integer>, Object>> indexFields, |
| 2016 |
Map<String, int64> fieldRecidByName)
|
|
| 2013 |
Map<String, integer> fieldRecidByName)
|
|
| 2017 | 2014 |
{
|
| 2018 | 2015 |
while (indices.hasNext()) |
| 2019 | 2016 |
{
|
| ... | ... | |
| 2021 | 2018 |
long id = nextId(metaDb, SystemTable._Index.fileName); |
| 2022 | 2019 |
if (idx.isPrimary()) |
| 2023 | 2020 |
{
|
| 2024 |
pk.assign(int64.of(id));
|
|
| 2021 |
pk.assign(integer.of(id));
|
|
| 2025 | 2022 |
} |
| 2026 | 2023 |
indexes.add(new MapBuilder<>(). |
| 2027 | 2024 |
put(Session.PK, id). |
| 2028 |
put("fileRecid", int64.of(_file_num)).
|
|
| 2025 |
put("fileRecid", integer.of(_file_num)).
|
|
| 2029 | 2026 |
put("indexName", new character(idx.getName())).
|
| 2030 | 2027 |
put("unique", logical.of(idx.isUnique())).
|
| 2031 | 2028 |
build() |
| ... | ... | |
| 2036 | 2033 |
{
|
| 2037 | 2034 |
P2JIndexComponent fld = comps.get(i); |
| 2038 | 2035 |
String compName = fld.getPropertyName(); |
| 2039 |
int64 fieldRecid = fieldRecidByName.get(compName);
|
|
| 2036 |
integer fieldRecid = fieldRecidByName.get(compName);
|
|
| 2040 | 2037 |
|
| 2041 | 2038 |
if (fieldRecid == null) |
| 2042 | 2039 |
{
|
| ... | ... | |
| 2045 | 2042 |
} |
| 2046 | 2043 |
indexFields.add(new MapBuilder<>(). |
| 2047 | 2044 |
put(Session.PK, nextId(metaDb, SystemTable._Index_Field.fileName)). |
| 2048 |
put("indexRecid", int64.of(id)).
|
|
| 2049 |
put("fieldRecid", fieldRecidByName.getOrDefault(compName, int64.UNKNOWN)).
|
|
| 2045 |
put("indexRecid", integer.of(id)).
|
|
| 2046 |
put("fieldRecid", fieldRecidByName.getOrDefault(compName, integer.UNKNOWN)).
|
|
| 2050 | 2047 |
put("indexSeq", integer.of(seqNo++)).
|
| 2051 | 2048 |
build() |
| 2052 | 2049 |
); |
| ... | ... | |
| 2072 | 2069 |
* @return _Field table data for a DMO field. |
| 2073 | 2070 |
*/ |
| 2074 | 2071 |
private static Map<Tuple<String, Integer>, Object> fieldData(Database metaDb, |
| 2075 |
long _file_num,
|
|
| 2072 |
int _file_num,
|
|
| 2076 | 2073 |
Property property, |
| 2077 | 2074 |
Class<?> ftype, |
| 2078 |
Map<String, int64> fieldRecidByName,
|
|
| 2075 |
Map<String, integer> fieldRecidByName,
|
|
| 2079 | 2076 |
Map<String, integer> fieldRposByName) |
| 2080 | 2077 |
{
|
| 2081 | 2078 |
long id = nextId(metaDb, SystemTable._Field.fileName); |
| 2082 |
fieldRecidByName.put(property.name, int64.of(id));
|
|
| 2079 |
fieldRecidByName.put(property.name, new integer(id));
|
|
| 2083 | 2080 |
fieldRposByName.put(property.name, integer.of(property.order)); |
| 2084 | 2081 |
int wd = property.width; |
| 2085 | 2082 |
integer width = wd >= 0 ? integer.of(wd) : integer.UNKNOWN; |
| ... | ... | |
| 2090 | 2087 |
String collation = charField ? (caseSensitive ? "basic_S" : "basic_I") : null; |
| 2091 | 2088 |
return new MapBuilder<>(). |
| 2092 | 2089 |
put(Session.PK, id). |
| 2093 |
put("fileRecid", int64.of(_file_num)).
|
|
| 2090 |
put("fileRecid", integer.of(_file_num)).
|
|
| 2094 | 2091 |
put("fieldName", new character(property.legacy)).
|
| 2095 | 2092 |
put("dataType", character.of(typeName)).
|
| 2096 | 2093 |
put("mandatory", logical.of(property.mandatory)).
|
| ... | ... | |
| 2739 | 2736 |
*/ |
| 2740 | 2737 |
public Map<Tuple<String, Integer>, Object> build( |
| 2741 | 2738 |
Class<? extends DataModelObject> dmoIface, |
| 2742 |
int64 pk,
|
|
| 2739 |
integer pk,
|
|
| 2743 | 2740 |
Map<SystemTable, List<Map<Tuple<String, Integer>, Object>>> children) |
| 2744 | 2741 |
{
|
| 2745 | 2742 |
Table table = dmoIface.getAnnotation(Table.class); |
| 2746 | 2743 |
int numfld = children.get(SystemTable._Field).size(); |
| 2747 | 2744 |
|
| 2748 |
return put("dbRecid", int64.of(DB_RECID)).
|
|
| 2745 |
return put("dbRecid", integer.of(DB_RECID)).
|
|
| 2749 | 2746 |
put("fileName", new character(table.legacy())).
|
| 2750 | 2747 |
put("owner", character.of("PUB")).
|
| 2751 | 2748 |
put("userMisc", new character(table.name())).
|
| new/src/com/goldencode/p2j/persist/orm/AbstractRowStructure.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 12 | 12 |
** 003 LS 20241105 Added hasOnlyPK(). |
| 13 | 13 |
** 004 OM 20240701 Replaced + concatenation with append in StringBuilder. |
| 14 | 14 |
** SP 20250321 Removed usage of prop.index. |
| 15 |
** 005 AL2 20231214 Fixed hydrate extents to avoid honoring recOffset if set on -1. |
|
| 15 | 16 |
*/ |
| 16 | 17 | |
| 17 | 18 |
/* |
| ... | ... | |
| 177 | 178 |
* @throws PersistenceException |
| 178 | 179 |
* thrown when hydrating extents fails (as it requires extra SQL queries to be run). |
| 179 | 180 |
*/ |
| 180 |
protected void hydrateExtents(Session session, BaseRecord r, int recOffset) |
|
| 181 |
@Override |
|
| 182 |
public void hydrateExtents(Session session, BaseRecord r, int recOffset) |
|
| 181 | 183 |
throws PersistenceException |
| 182 | 184 |
{
|
| 183 | 185 |
// TODO: collect extent properties and do a new query from SQL, see Loader.readExtentData() |
| ... | ... | |
| 188 | 190 |
PropertyMeta[] propsMeta = recordMeta.getPropertyMeta(false); |
| 189 | 191 |
String[] loadSqls = recordMeta.loadSql; |
| 190 | 192 |
int[] loadSqlsIndexes = recordMeta.loadSqlIndexes; |
| 191 |
boolean incomplete = isIncomplete();
|
|
| 193 |
boolean arbitrary = isIncomplete() || recOffset == -1;
|
|
| 192 | 194 |
|
| 193 | 195 |
// only use the extent queries, skip the loadSqls[0] which contains the simple properties |
| 194 | 196 |
for (int i = 1; i < loadSqls.length; i++) // skip "plain" columns |
| 195 | 197 |
{
|
| 196 |
if (incomplete)
|
|
| 198 |
if (arbitrary)
|
|
| 197 | 199 |
{
|
| 198 | 200 |
// resolve the offset in the 'props' array where this sql starts. |
| 199 | 201 |
// all non-expanded extent fields are loaded even for incomplete records. |
| new/src/com/goldencode/p2j/persist/orm/AdaptiveRowStructure.java 2026-05-22 13:58:35 +0000 | ||
|---|---|---|
| 10 | 10 |
** AL2 20231212 Use dmoMeta directly, without getter. |
| 11 | 11 |
** 002 OM 20240715 Fixed copy/paste bug. |
| 12 | 12 |
** 003 LS 20250714 Added 'getNeededFields' implementation. |
| 13 |
** 004 AL2 20231214 Added implementation for hydrateAt. |
|
| 13 | 14 |
*/ |
| 14 | 15 | |
| 15 | 16 |
/* |
| ... | ... | |
| 69 | 70 | |
| 70 | 71 |
import java.sql.ResultSet; |
| 71 | 72 |
import java.sql.SQLException; |
| 72 |
import java.util.BitSet; |
|
| 73 |
import java.util.Iterator; |
|
| 73 |
import java.util.*; |
|
| 74 | 74 | |
| 75 | 75 |
import com.goldencode.p2j.persist.*; |
| 76 | 76 | |
| ... | ... | |
| 228 | 228 |
return delegate.getNeededFields(); |
| 229 | 229 |
} |
| 230 | 230 | |
| 231 | ||
| 232 |
/** |
|
| 233 |
* Hydrate only one property in the base-record. This is largely used by the lazy hydrator, |
|
| 234 |
* allowing it to hydrate only the property that is accessed now. The other hydration method |
|
| 235 |
* ({@link #hydrate}) eagerly hydrates all properties, is a slow process and may do useless
|
|
| 236 |
* hydrations on properties that are not accessed. |
|
| 237 |
* |
|
| 238 |
* @param resultSet |
|
| 239 |
* The ResultSet from which the hydration should be done |
|
| 240 |
* @param rsOffset |
|
| 241 |
* The result set offset from which the reading should be done. This is relevant as |
|
| 242 |
* the result set may contain a joined row, but we are interested only in a specific |
|
| 243 |
* record that may start at a specific offset. |
|
| 244 |
* @param r |
|
| 245 |
* The record that should be hydrated. |
|
| 246 |
* @param propOffset |
|
| 247 |
* The property that should be hydrated. The caller is responsible in assuring that |
|
| 248 |
* this property wasn't hydrated before. |
|
| 249 |
* |
|
| 250 |
* @return {@code true} if this worked due to the fact that it was a scalar value. {@code false}
|
|
| 251 |
* in case the property was a non-expanded |
|
| 252 |
* |
|
| 253 |
* @throws PersistenceException |
|
| 254 |
* This is thrown when reading the scalar property fails. |
|
| 255 |
*/ |
|
| 256 |
@Override |
|
| 257 |
public boolean hydrateAt(ResultSet resultSet, int rsOffset, BaseRecord r, int dataIndex) |
|
| 258 |
throws PersistenceException |
|
| 259 |
{
|
|
| 260 |
return delegate.hydrateAt(resultSet, rsOffset, r, dataIndex); |
|
| 261 |
} |
|
| 262 |
|
|
| 263 |
/** |
|
| 264 |
* Retrieve the fields that were loaded from the database. |
|
| 265 |
* |
|
| 266 |
* @return A BitSet object, where true means that the field associated with that position in the {@code
|
|
| 267 |
* data} array has been loaded from database, and false - otherwise. |
|
| 268 |
*/ |
|
| 269 |
@Override |
|
| 270 |
public BitSet getLoadedFields() |
|
| 271 |
{
|
|