7035-20230209.patch
new/src/com/goldencode/p2j/jmx/FwdJMX.java 2023-02-09 11:37:06 +0000 | ||
---|---|---|
25 | 25 |
** AL2 20230104 Added OrmRedo. |
26 | 26 |
** Added OrmNoUndoTrace. |
27 | 27 |
** OM 20230112 Added finer-granulation instrumentation for processing of dynamic queries. |
28 |
** DDF 20230209 Added counters for psCache (prepared statement cache) hit/miss. (refs: #7035) |
|
28 | 29 |
*/ |
29 | 30 | |
30 | 31 |
/* |
... | ... | |
551 | 552 |
/** Outgoing network traffic */ |
552 | 553 |
NetworkWrites, |
553 | 554 |
/** Widget attributes flush count */ |
554 |
WidgetAttrFlushes; |
|
555 |
WidgetAttrFlushes, |
|
556 |
/** psCache hit counter */ |
|
557 |
PSCacheHits, |
|
558 |
/** psCache miss counter */ |
|
559 |
PSCacheMisses; |
|
555 | 560 |
|
556 | 561 |
/** Counter instance */ |
557 | 562 |
private final SimpleLongCounter counter = new SimpleLongCounter(); |
new/src/com/goldencode/p2j/persist/FQLBundle.java 2023-02-09 11:38:33 +0000 | ||
---|---|---|
19 | 19 |
** 008 EVL 20160223 Javadoc fixes to make compatible with Oracle Java 8 for Solaris 10. |
20 | 20 |
** 009 ECF 20200906 New ORM implementation. |
21 | 21 |
** 010 OM 20221103 Renamed class to FQLBundle. |
22 |
** 011 DDF 20230209 Refactored ParameterIndices into ParameterDiff. (refs: #7035) |
|
22 | 23 |
*/ |
23 | 24 | |
24 | 25 |
/* |
... | ... | |
153 | 154 |
/** Parallel set of FQL statements for dirty database use */ |
154 | 155 |
private List<String> dirtyStatements = null; |
155 | 156 |
|
156 |
/** Mapping of indices in the array of query substitution parameters */
|
|
157 |
private ParameterIndices paramIndices = null;
|
|
157 |
/** Mapping of substitution parameters functions */
|
|
158 |
private ParameterDiff paramDiff = null;
|
|
158 | 159 |
|
159 | 160 |
/** |
160 | 161 |
* Default constructor. |
... | ... | |
347 | 348 |
} |
348 | 349 |
|
349 | 350 |
/** |
350 |
* Get the <code>ParameterIndices</code> object associated with this
|
|
351 |
* Get the <code>ParameterDiff</code> object associated with this
|
|
351 | 352 |
* bundle. This object maintains an array of zero-based indices into the |
352 |
* array of query substitution arguments for the base (i.e., unaugmented)
|
|
353 |
* array of query substitution parameters lambdas for the base (i.e., unaugmented)
|
|
353 | 354 |
* where clause, as it exists <i>after</i> preprocessing is complete. This |
354 | 355 |
* additional level of indirection is necessary because the query |
355 | 356 |
* substitution placeholders may have been reordered within the FQL where |
356 | 357 |
* clause expression during the FQL preprocessing rewrite step, and some |
357 | 358 |
* parameters may have been inlined into the where clause. |
358 | 359 |
* |
359 |
* @return An object which provides a mapping of indices into the query
|
|
360 |
* substitution parameter list.
|
|
360 |
* @return An object which provides a mapping of query substitution parameter
|
|
361 |
* functions.
|
|
361 | 362 |
*/ |
362 |
ParameterIndices getParameterIndices()
|
|
363 |
ParameterDiff getParameterDiff()
|
|
363 | 364 |
{ |
364 |
return paramIndices;
|
|
365 |
return paramDiff;
|
|
365 | 366 |
} |
366 | 367 |
|
367 | 368 |
/** |
368 |
* Set the <code>ParameterIndices</code> object associated with this
|
|
369 |
* Set the <code>ParameterDiff</code> object associated with this
|
|
369 | 370 |
* bundle. This object maintains an array of zero-based indices into the |
370 |
* array of query substitution arguments for the base (i.e., unaugmented)
|
|
371 |
* array of query substitution parameters lambdas for the base (i.e., unaugmented)
|
|
371 | 372 |
* where clause, as it exists <i>after</i> preprocessing is complete. This |
372 | 373 |
* additional level of indirection is necessary because the query |
373 | 374 |
* substitution placeholders may have been reordered within the FQL where |
... | ... | |
375 | 376 |
* parameters may have been inlined into the where clause. |
376 | 377 |
* |
377 | 378 |
* @param paramIndices |
378 |
* An object which provides a mapping of indices into the query
|
|
379 |
* substitution parameter list.
|
|
379 |
* An object which provides a mapping of query substitution parameter
|
|
380 |
* functions.
|
|
380 | 381 |
*/ |
381 |
void setParameterIndices(ParameterIndices paramIndices)
|
|
382 |
void setParameterDiff(ParameterDiff paramDiff)
|
|
382 | 383 |
{ |
383 |
this.paramIndices = paramIndices;
|
|
384 |
this.paramDiff = paramDiff;
|
|
384 | 385 |
} |
385 | 386 |
|
386 | 387 |
/** |
new/src/com/goldencode/p2j/persist/FQLHelper.java 2023-02-09 11:38:58 +0000 | ||
---|---|---|
130 | 130 |
** prevent NPE in proxy case. |
131 | 131 |
** CA 20221006 Added JMX instrumentation for FQL prepare (in 'obtain'). Refs #6814 |
132 | 132 |
** OM 20221103 Class renamed to FQLHelper. |
133 |
** DDF 20230209 Method call changed due to method refactoring of FQLBundle and |
|
134 |
** FQLPreprocessor. (refs: #7035) |
|
133 | 135 |
*/ |
134 | 136 | |
135 | 137 |
/* |
... | ... | |
971 | 973 |
} |
972 | 974 |
} |
973 | 975 |
|
974 |
// Store query substitution parameter indices.
|
|
976 |
// Store query substitution parameter lambdas.
|
|
975 | 977 |
// TODO: currently, these are shared, and not dialect specific, but |
976 | 978 |
// only because we do not inline parameters from this class. Were this |
977 |
// to change, we would need to maintain separate ParameterIndices
|
|
979 |
// to change, we would need to maintain separate ParameterDiff
|
|
978 | 980 |
// objects for the primary and dirty database statements. |
979 | 981 |
if (primary) |
980 | 982 |
{ |
981 |
bundle.setParameterIndices(fqlPreprocessor.getParameterIndices());
|
|
983 |
bundle.setParameterDiff(fqlPreprocessor.getParameterDiff());
|
|
982 | 984 |
} |
983 | 985 |
} |
984 | 986 |
|
new/src/com/goldencode/p2j/persist/FQLPreprocessor.java 2023-02-09 11:40:23 +0000 | ||
---|---|---|
282 | 282 |
** are not the same), to be aware of the external buffers (i.e. added for CAN-FIND |
283 | 283 |
** sub-select clauses). The translate will be performed before the query is being |
284 | 284 |
** executed. |
285 |
** DDF 20230209 Extracted query parameters from the where clause and refactored ParameterIndices |
|
286 |
** into ParameterDiff to store a mapping of substitution parameter lambdas for all |
|
287 |
** parameters (parameters given at query initialization and the ones extracted |
|
288 |
** from the AST). (refs: #7035) |
|
285 | 289 |
*/ |
286 | 290 | |
287 | 291 |
/* |
... | ... | |
467 | 471 |
* substitution parameters in the proper order: |
468 | 472 |
* <ul> |
469 | 473 |
* <li>{@link #getFQL()} |
470 |
* <li>{@link #getParameterIndices()}
|
|
474 |
* <li>{@link #getParameterDiff()}
|
|
471 | 475 |
* <li>{@link #ansiJoins()} |
472 | 476 |
* </ul> |
473 | 477 |
* <p> |
... | ... | |
615 | 619 |
*/ |
616 | 620 |
private boolean inlinedTernary = false; |
617 | 621 |
|
618 |
/** Mapping of index positions for substitution parameters after rewrite */
|
|
619 |
private ParameterIndices paramIndices = null;
|
|
622 |
/** Mapping of substitution parameters functions after rewrite */
|
|
623 |
private ParameterDiff paramDiff = null;
|
|
620 | 624 |
|
621 | 625 |
/** Map of properties used by this where clause, keyed by DMO entity */ |
622 | 626 |
private Map<String, Set<String>> restrictionProperties = null; |
... | ... | |
1289 | 1293 |
} |
1290 | 1294 |
|
1291 | 1295 |
/** |
1292 |
* Get the <code>ParameterIndices</code> object associated with this query.
|
|
1296 |
* Get the <code>ParameterDiff</code> object associated with this query.
|
|
1293 | 1297 |
* This object maintains an array of zero-based indices into the array of |
1294 |
* query substitution arguments for the where clause, as it exists
|
|
1298 |
* query substitution parameter lambdas for the where clause, as it exists
|
|
1295 | 1299 |
* <i>after</i> preprocessing is complete. This additional level of |
1296 | 1300 |
* indirection is necessary because the query substitution placeholders may |
1297 | 1301 |
* have been reordered within the FQL where clause expression during the |
... | ... | |
1299 | 1303 |
* inlined into the where clause. |
1300 | 1304 |
* |
1301 | 1305 |
* @return An object which provides a mapping of indices into the query |
1302 |
* substitution parameter list. |
|
1306 |
* substitution parameter lambdas list.
|
|
1303 | 1307 |
*/ |
1304 |
ParameterIndices getParameterIndices()
|
|
1308 |
ParameterDiff getParameterDiff()
|
|
1305 | 1309 |
{ |
1306 |
return paramIndices;
|
|
1310 |
return paramDiff;
|
|
1307 | 1311 |
} |
1308 | 1312 |
|
1309 | 1313 |
/** |
... | ... | |
1554 | 1558 |
|
1555 | 1559 |
this.findByRowid = checkFindByRowid(root); |
1556 | 1560 |
|
1561 |
// parameters need to be created before fql is emitted |
|
1562 |
this.paramDiff = createParameterDiffs(root, parameters); |
|
1563 |
|
|
1557 | 1564 |
// Emit the preprocessed FQL expression text. |
1558 | 1565 |
this.fql = emit(root, false); |
1559 | 1566 |
|
... | ... | |
1563 | 1570 |
LOG.log(Level.FINEST, |
1564 | 1571 |
"[" + database + "] Preprocessed FQL: " + fql + sep + root.dumpTree()); |
1565 | 1572 |
} |
1566 |
|
|
1567 |
this.paramIndices = createParameterIndices(root, parameters); |
|
1568 | 1573 |
} |
1569 | 1574 |
} |
1570 | 1575 |
|
... | ... | |
5849 | 5854 |
} |
5850 | 5855 |
|
5851 | 5856 |
/** |
5852 |
* Create the mapping of substitution parameters to their corresponding |
|
5857 |
* Create the mapping of substitution parameters functions to their corresponding
|
|
5853 | 5858 |
* substitution placeholders in the rewritten FQL where clause. These |
5854 | 5859 |
* placeholders (<code>?</code>) may have been reordered or removed (due to |
5855 | 5860 |
* inlining) during the rewrite process. |
5856 | 5861 |
* <p> |
5857 | 5862 |
* During parsing of the FQL clause, an index annotation was added to each |
5858 | 5863 |
* AST of type <code>SUBST</code> (token type for the query substitution |
5859 |
* parameter placeholder), denoting that placeholder's position in the |
|
5860 |
* original where clause. We now walk the rewritten AST, extracting this |
|
5861 |
* annotation and storing it in a new list. The resulting array defines |
|
5864 |
* parameter placeholder), and each <code>NUM_LITERAL</code>, <code>DEC_LITERAL</code>, |
|
5865 |
* <code>STRING</code> which is substituted to <code>SUBST</code> |
|
5866 |
* denoting that placeholder's lambda in the original where clause. |
|
5867 |
* We now walk the rewritten AST, extracting this annotation |
|
5868 |
* and storing it in a new list. The resulting array defines |
|
5862 | 5869 |
* the new order of the substitution parameters. For parameters which |
5863 | 5870 |
* were dropped, due to inlining, a null placeholder will appear in the new |
5864 | 5871 |
* list. |
... | ... | |
5871 | 5878 |
* @return Object which maps new query substitution parameter positions to their positions in the original |
5872 | 5879 |
* parameters array. These indices are zero-based. |
5873 | 5880 |
*/ |
5874 |
private ParameterIndices createParameterIndices(HQLAst root, Object[] parameters)
|
|
5881 |
private ParameterDiff createParameterDiffs(HQLAst root, Object[] parameters)
|
|
5875 | 5882 |
{ |
5876 |
if (parameters == null) |
|
5877 |
{ |
|
5878 |
return (new ParameterIndices(null)); |
|
5879 |
} |
|
5883 |
int parameterCounter = parameters != null ? parameters.length : 0; |
|
5884 |
FqlType parameterType = null; |
|
5880 | 5885 |
|
5881 |
List<Integer> indices = new ArrayList<>(parameters.length);
|
|
5886 |
List<Function<Object[], Object>> retrieveParameterFunctions = new ArrayList<>();
|
|
5882 | 5887 |
|
5883 | 5888 |
// Extract the "index" annotation from each SUBST node, in order of |
5884 | 5889 |
// the tree walk, which will correspond to the order of the placeholders |
5885 | 5890 |
// in the final, infix expression. |
5891 |
|
|
5892 |
// There are two types of parameters, parameters that are substituted from the beginning, |
|
5893 |
// and those that are substituted in the mainWalk() method. |
|
5894 |
// In the case of the "extracted-value" annotation being present, create a function |
|
5895 |
// that returns the value after being casted to a BaseDataType. |
|
5896 |
// For the substituted parameters that already existed, the function returns |
|
5897 |
// the index positioned value in the params given. |
|
5886 | 5898 |
Iterator<Aast> iter = root.iterator(); |
5887 | 5899 |
while (iter.hasNext()) |
5888 | 5900 |
{ |
5889 |
Long index = null; |
|
5890 | 5901 |
HQLAst next = (HQLAst) iter.next(); |
5891 | 5902 |
switch (next.getType()) |
5892 |
{ |
|
5893 |
case SUBST: |
|
5894 |
index = (Long) next.getAnnotation("index"); |
|
5895 |
indices.add(index.intValue()); |
|
5896 |
break; |
|
5897 |
|
|
5903 |
{ |
|
5904 |
// The BOOL_TRUE and BOOL_FALSE cases are not handled |
|
5898 | 5905 |
case NUM_LITERAL: |
5906 |
if (parameterType == null) |
|
5907 |
{ |
|
5908 |
parameterType = FqlType.INTEGER; |
|
5909 |
} |
|
5899 | 5910 |
case DEC_LITERAL: |
5911 |
if (parameterType == null) |
|
5912 |
{ |
|
5913 |
parameterType = FqlType.DECIMAL; |
|
5914 |
} |
|
5900 | 5915 |
case STRING: |
5901 |
case IS_NULL: |
|
5902 |
case NOT_NULL: |
|
5903 |
case BOOL_FALSE: |
|
5916 |
if (parameterType == null) |
|
5917 |
{ |
|
5918 |
parameterType = FqlType.TEXT; |
|
5919 |
} |
|
5920 |
|
|
5904 | 5921 |
if (inline && next.isAnnotation("inlined")) |
5905 | 5922 |
{ |
5906 |
// Allow null to remain at this position in the array. |
|
5907 |
indices.add(null); |
|
5908 |
} |
|
5923 |
break; |
|
5924 |
} |
|
5925 |
|
|
5926 |
// Add an index and datatype annotation to the current node. |
|
5927 |
// The extracted-value annotation stores the value of the node. |
|
5928 |
next.putAnnotation("index", (long) parameterCounter++); |
|
5929 |
next.putAnnotation("datatype", parameterType.toString()); |
|
5930 |
next.putAnnotation("extracted-value", next.getText()); |
|
5931 |
parameterType = null; |
|
5932 |
|
|
5933 |
// Change the node type and value |
|
5934 |
next.setType(SUBST); |
|
5935 |
next.setText("?"); |
|
5936 |
case SUBST: |
|
5937 |
Function<Object[], Object> rp = null; |
|
5938 |
|
|
5939 |
if (next.isAnnotation("extracted-value")) |
|
5940 |
{ |
|
5941 |
rp = (Object[] params) -> |
|
5942 |
{ |
|
5943 |
String value = (String) next.getAnnotation("extracted-value"); |
|
5944 |
FqlType fqlType = Enum.valueOf(FqlType.class, (String) next.getAnnotation("datatype")); |
|
5945 |
switch (fqlType) |
|
5946 |
{ |
|
5947 |
case INTEGER: |
|
5948 |
return new integer(value); |
|
5949 |
case DECIMAL: |
|
5950 |
return new decimal(value); |
|
5951 |
case TEXT: |
|
5952 |
assert (value.charAt(0) == '\''); |
|
5953 |
assert (value.charAt(value.length() - 1) == '\''); |
|
5954 |
value = value.substring(1, value.length() - 1); |
|
5955 |
return new character(value); |
|
5956 |
default: |
|
5957 |
throw new IllegalStateException("No matching datatype for the extracted value."); |
|
5958 |
} |
|
5959 |
}; |
|
5960 |
} |
|
5961 |
else |
|
5962 |
{ |
|
5963 |
rp = (Object[] params) -> |
|
5964 |
{ |
|
5965 |
Long index = (Long) next.getAnnotation("index"); |
|
5966 |
return params[index.intValue()]; |
|
5967 |
}; |
|
5968 |
} |
|
5969 |
|
|
5970 |
retrieveParameterFunctions.add(rp); |
|
5909 | 5971 |
break; |
5910 | 5972 |
|
5911 | 5973 |
default: |
... | ... | |
5913 | 5975 |
} |
5914 | 5976 |
} |
5915 | 5977 |
|
5916 |
Integer[] idx = indices.toArray(new Integer[indices.size()]); |
|
5917 |
|
|
5918 |
return (new ParameterIndices(idx)); |
|
5978 |
if (retrieveParameterFunctions.size() == 0) |
|
5979 |
{ |
|
5980 |
return new ParameterDiff(null); |
|
5981 |
} |
|
5982 |
|
|
5983 |
@SuppressWarnings("unchecked") |
|
5984 |
Function<Object[], Object>[] rpf = retrieveParameterFunctions.toArray(new Function[] {}); |
|
5985 |
|
|
5986 |
return new ParameterDiff(rpf); |
|
5919 | 5987 |
} |
5920 | 5988 |
|
5921 | 5989 |
/** |
new/src/com/goldencode/p2j/persist/ParameterDiff.java 2023-02-07 13:27:23 +0000 | ||
---|---|---|
1 |
/* |
|
2 |
** Module : ParameterDiff.java |
|
3 |
** Abstract : Mapping of query substitution parameters functions in an array, after where clause preprocessing. |
|
4 |
** |
|
5 |
** Copyright (c) 2008-2023, Golden Code Development Corporation. |
|
6 |
** |
|
7 |
** -#- -I- --Date-- -JPRM- ------------------------------------Description------------------------------------ |
|
8 |
** 001 ECF 20081009 @40080 Created initial version. A mapping of query substitution parameters in an array, |
|
9 |
** after where clause preprocessing. |
|
10 |
** 002 OM 20221103 New class names for FQLPreprocessor, FQLExpression, FQLBundle, and FQLCache. |
|
11 |
** 003 DDF 20230201 Refactored ParameterIndices into ParameterDiff by replacing the Integer indices |
|
12 |
** array with an array of lambdas. Instead of storing the index of the parameters |
|
13 |
** from the AST node, we store a lambda that takes an array of arguments and returns |
|
14 |
** either an extracted value from the AST, or an existing value from the given array. |
|
15 |
*/ |
|
16 | ||
17 |
/* |
|
18 |
** This program is free software: you can redistribute it and/or modify |
|
19 |
** it under the terms of the GNU Affero General Public License as |
|
20 |
** published by the Free Software Foundation, either version 3 of the |
|
21 |
** License, or (at your option) any later version. |
|
22 |
** |
|
23 |
** This program is distributed in the hope that it will be useful, |
|
24 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
25 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
26 |
** GNU Affero General Public License for more details. |
|
27 |
** |
|
28 |
** You may find a copy of the GNU Affero GPL version 3 at the following |
|
29 |
** location: https://www.gnu.org/licenses/agpl-3.0.en.html |
|
30 |
** |
|
31 |
** Additional terms under GNU Affero GPL version 3 section 7: |
|
32 |
** |
|
33 |
** Under Section 7 of the GNU Affero GPL version 3, the following additional |
|
34 |
** terms apply to the works covered under the License. These additional terms |
|
35 |
** are non-permissive additional terms allowed under Section 7 of the GNU |
|
36 |
** Affero GPL version 3 and may not be removed by you. |
|
37 |
** |
|
38 |
** 0. Attribution Requirement. |
|
39 |
** |
|
40 |
** You must preserve all legal notices or author attributions in the covered |
|
41 |
** work or Appropriate Legal Notices displayed by works containing the covered |
|
42 |
** work. You may not remove from the covered work any author or developer |
|
43 |
** credit already included within the covered work. |
|
44 |
** |
|
45 |
** 1. No License To Use Trademarks. |
|
46 |
** |
|
47 |
** This license does not grant any license or rights to use the trademarks |
|
48 |
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks |
|
49 |
** of Golden Code Development Corporation. You are not authorized to use the |
|
50 |
** name Golden Code, FWD, or the names of any author or contributor, for |
|
51 |
** publicity purposes without written authorization. |
|
52 |
** |
|
53 |
** 2. No Misrepresentation of Affiliation. |
|
54 |
** |
|
55 |
** You may not represent yourself as Golden Code Development Corporation or FWD. |
|
56 |
** |
|
57 |
** You may not represent yourself for publicity purposes as associated with |
|
58 |
** Golden Code Development Corporation, FWD, or any author or contributor to |
|
59 |
** the covered work, without written authorization. |
|
60 |
** |
|
61 |
** 3. No Misrepresentation of Source or Origin. |
|
62 |
** |
|
63 |
** You may not represent the covered work as solely your work. All modified |
|
64 |
** versions of the covered work must be marked in a reasonable way to make it |
|
65 |
** clear that the modified work is not originating from Golden Code Development |
|
66 |
** Corporation or FWD. All modified versions must contain the notices of |
|
67 |
** attribution required in this license. |
|
68 |
*/ |
|
69 | ||
70 |
package com.goldencode.p2j.persist; |
|
71 | ||
72 |
import java.util.function.Function; |
|
73 | ||
74 |
/** |
|
75 |
* A mapping of the active indices in an array of query substitution |
|
76 |
* parameters, after an HQL where clause has been preprocessed. The HQL |
|
77 |
* preprocessor may inline or re-order query substitution parameters. Thus, |
|
78 |
* given an array of query substitution parameters, it is necessary to provide |
|
79 |
* a means for a query object to organize the remaining parameters when |
|
80 |
* submitting a query for execution. |
|
81 |
* <p> |
|
82 |
* A query object will have the original array of parameters provided by |
|
83 |
* business logic, as well as an instance of {@link FQLPreprocessor}. That |
|
84 |
* instance will provide an instance of this class via its {@link |
|
85 |
* FQLPreprocessor#getParameterDiff()} method. To obtain the correct list |
|
86 |
* of parameters which corresponds with the preprocessed where clause, the |
|
87 |
* query iterates its original array of parameters. For each index in that |
|
88 |
* array, it calls {@link #getIndex(int)} to obtain the remapped position of |
|
89 |
* the parameter originally at the current index. If <code>null</code> is |
|
90 |
* returned, it means the parameter originally at the current index has been |
|
91 |
* inlined into the where clause. A non-<code>null</code> value represents |
|
92 |
* the zero-based index at which the parameter can be found in the original |
|
93 |
* array. |
|
94 |
*/ |
|
95 |
final class ParameterDiff |
|
96 |
{ |
|
97 |
/** Count of substitution parameters functions in use */ |
|
98 |
private final int count; |
|
99 |
|
|
100 |
/** Array of functions for substitution parameters */ |
|
101 |
private final Function<Object[], Object>[] substParamFunctions; |
|
102 |
|
|
103 |
/** |
|
104 |
* Constructor which sets the array of substitution parameters |
|
105 |
* functions of query for the associated where clause. |
|
106 |
* |
|
107 |
* @param substFunctions |
|
108 |
* Array of substitution parameter functions. If |
|
109 |
* <code>null</code>, the associated query string has no query |
|
110 |
* substitution parameters. |
|
111 |
*/ |
|
112 |
ParameterDiff(Function<Object[], Object>[] substFunctions) |
|
113 |
{ |
|
114 |
this.substParamFunctions = substFunctions; |
|
115 |
int counter = 0; |
|
116 |
if (substParamFunctions != null) |
|
117 |
{ |
|
118 |
for (int i = 0; i < substParamFunctions.length; i++) |
|
119 |
{ |
|
120 |
if (substParamFunctions[i] == null) |
|
121 |
{ |
|
122 |
continue; |
|
123 |
} |
|
124 |
counter++; |
|
125 |
} |
|
126 |
} |
|
127 |
this.count = counter; |
|
128 |
} |
|
129 |
|
|
130 |
/** |
|
131 |
* Get the count of query substitution parameters functions which were created for |
|
132 |
* the where clause preprocessing step. This is the count of the passed |
|
133 |
* lambda array items to this object's constructor. |
|
134 |
* |
|
135 |
* @return Count of query substitution parameters functions. |
|
136 |
*/ |
|
137 |
int getCount() |
|
138 |
{ |
|
139 |
return count; |
|
140 |
} |
|
141 |
|
|
142 |
/** |
|
143 |
* Given a position of a query substitution parameter function in the original |
|
144 |
* array of lambdas (before the where clause preprocessing step), get the |
|
145 |
* lambda of that parameter in the original array. Note that the |
|
146 |
* original array is not changed, only the mapping of lambdas may have |
|
147 |
* changed. If the index returned matches the <code>position</code> |
|
148 |
* supplied, this indicates the parameter's placeholder (<code>?</code>) is |
|
149 |
* located at the same relative position in the where clause as before |
|
150 |
* preprocessing. |
|
151 |
* |
|
152 |
* @param position |
|
153 |
* Zero-based index of the target substitution parameter function |
|
154 |
* in the original array. |
|
155 |
* |
|
156 |
* @return New, zero-based index of the target substitution parameter function |
|
157 |
* in the original array, or <code>null</code> if the parameter was |
|
158 |
* inlined during preprocessing of the where clause. |
|
159 |
*/ |
|
160 |
Function<Object[], Object> getIndex(int position) |
|
161 |
{ |
|
162 |
return (substParamFunctions == null ? null : substParamFunctions[position]); |
|
163 |
} |
|
164 |
|
|
165 |
/** |
|
166 |
* Method for retrieving the substitution parameter functions. |
|
167 |
* |
|
168 |
* @return The substitution parameter functions, or null if |
|
169 |
* no functions were assigned. |
|
170 |
*/ |
|
171 |
Function<Object[], Object>[] getSubstParamFunctions() |
|
172 |
{ |
|
173 |
return substParamFunctions; |
|
174 |
} |
|
175 |
|
|
176 |
/** |
|
177 |
* Apply the substitution parameters lambdas based on the params given. The params |
|
178 |
* value is used just for already substituded parameters from the where clause, |
|
179 |
* while the value of the subtituted parameters from the preprocessing are replaced |
|
180 |
* by the value of the node annotation <code>extracted-value</code>. |
|
181 |
* |
|
182 |
* @param params |
|
183 |
* Parameter array for lambda which selects the parameter value |
|
184 |
* for substituted parameters that were not created during |
|
185 |
* the preprocessing phase. |
|
186 |
* The parameter array is still required for the other lambdas, |
|
187 |
* but not used. |
|
188 |
* |
|
189 |
* @return Object representing the value of the argument. |
|
190 |
*/ |
|
191 |
Object[] getSubstParameters(Object[] params) |
|
192 |
{ |
|
193 |
if (substParamFunctions == null) |
|
194 |
{ |
|
195 |
return null; |
|
196 |
} |
|
197 |
|
|
198 |
Object[] args = new Object[count]; |
|
199 |
for (int position = 0; position < substParamFunctions.length; position++) |
|
200 |
{ |
|
201 |
if (substParamFunctions[position] != null) |
|
202 |
{ |
|
203 |
args[position] = substParamFunctions[position].apply(params); |
|
204 |
} |
|
205 |
} |
|
206 |
return args; |
|
207 |
} |
|
208 |
} |
new/src/com/goldencode/p2j/persist/QueryComponent.java 2023-02-09 11:40:53 +0000 | ||
---|---|---|
32 | 32 |
** CA 20221130 Refactored the WHERE clause translation (when the bound and definition buffers are not the |
33 | 33 |
** same), to be aware of the external buffers (i.e. added for CAN-FIND sub-select clauses). |
34 | 34 |
** The translate will be performed before the query is being executed. |
35 |
** DDF 20230209 Refactored ParameterIndices into ParameterDiff. Extracted arguments also need to be |
|
36 |
** resolved. (refs: #7035) |
|
35 | 37 |
*/ |
36 | 38 | |
37 | 39 |
/* |
... | ... | |
490 | 492 |
protected Object[] getArgs() |
491 | 493 |
throws PersistenceException |
492 | 494 |
{ |
493 |
if (dfArgs != null && currentArgs == null)
|
|
495 |
if (currentArgs == null) |
|
494 | 496 |
{ |
495 | 497 |
currentArgs = filterArgs(getHQLPreprocessor()); |
496 | 498 |
} |
... | ... | |
594 | 596 |
// in this case the processDynamicFilters() is not required to be called before calling |
595 | 597 |
// resolveArgs() because it was called before constructing the preprocessor |
596 | 598 |
Object[] intermediate = resolveArgs(); |
597 |
if (intermediate == null) |
|
598 |
{ |
|
599 |
return null; |
|
600 |
} |
|
601 |
|
|
602 |
ParameterIndices pi = preproc.getParameterIndices(); |
|
603 |
int len = pi.getCount(); |
|
604 |
Object[] filteredArgs = new Object[len]; |
|
605 |
for (int i = 0, count = 0; count < len; i++) |
|
606 |
{ |
|
607 |
Integer nextIndex = pi.getIndex(i); |
|
608 |
if (nextIndex == null) |
|
609 |
{ |
|
610 |
// original substitution parameter was inlined into HQL by preprocessor; skip it |
|
611 |
continue; |
|
612 |
} |
|
613 |
|
|
614 |
// Substitution placeholders may have been reordered if this |
|
615 |
// statement was rewritten by the HQL preprocessor. Make sure |
|
616 |
// we access the correct substitution parameter. |
|
617 |
Object next = intermediate[nextIndex]; |
|
618 |
|
|
619 |
filteredArgs[count++] = next; |
|
599 |
ParameterDiff pd = preproc.getParameterDiff(); |
|
600 |
if (intermediate == null && pd == null) |
|
601 |
{ |
|
602 |
return null; |
|
603 |
} |
|
604 |
|
|
605 |
if (pd == null) |
|
606 |
{ |
|
607 |
return intermediate; |
|
608 |
} |
|
609 | ||
610 |
Object[] filteredArgs = pd.getSubstParameters(intermediate); |
|
611 |
|
|
612 |
if (filteredArgs == null) |
|
613 |
{ |
|
614 |
return null; |
|
615 |
} |
|
616 |
|
|
617 |
for (int i = 0; i < filteredArgs.length; i++) |
|
618 |
{ |
|
619 |
// Substitution parameters returned also need to be resolved. |
|
620 |
filteredArgs[i] = resolveArg(filteredArgs[i]); |
|
620 | 621 |
} |
621 | 622 |
|
622 | 623 |
return filteredArgs; |
new/src/com/goldencode/p2j/persist/RandomAccessQuery.java 2023-02-09 11:41:19 +0000 | ||
---|---|---|
347 | 347 |
** are not the same), to be aware of the external buffers (i.e. added for CAN-FIND |
348 | 348 |
** sub-select clauses). The translate will be performed before the query is being |
349 | 349 |
** executed. |
350 |
** DDF 20230209 Refactoring ParameterIndices into ParameterDiff and added method for retrieving |
|
351 |
** parameter values. (refs: #7035) |
|
350 | 352 |
*/ |
351 | 353 | |
352 | 354 |
/* |
... | ... | |
4251 | 4253 |
boolean debug = LOG.isLoggable(Level.FINE); |
4252 | 4254 |
|
4253 | 4255 |
DirtyShareContext dirtyContext = buffer.getDirtyContext(); |
4254 |
ParameterIndices pi = activeBundle.getParameterIndices();
|
|
4256 |
ParameterDiff pi = activeBundle.getParameterDiff();
|
|
4255 | 4257 |
int origArgCount = (values == null ? 0 : values.length); |
4256 | 4258 |
int baseArgCount = (pi == null ? origArgCount : pi.getCount()); |
4257 | 4259 |
|
... | ... | |
4338 | 4340 |
// resolve these parameters. |
4339 | 4341 |
for (int j = 0, i = startIndex; i < baseArgCount; j++) |
4340 | 4342 |
{ |
4341 |
int k = -1; |
|
4342 |
if (pi == null) |
|
4343 |
{ |
|
4344 |
k = j; |
|
4345 |
} |
|
4346 |
else |
|
4347 |
{ |
|
4348 |
Integer idx = pi.getIndex(j); |
|
4349 |
if (idx == null) |
|
4350 |
{ |
|
4351 |
// original substitution parameter was inlined into HQL by preprocessor; skip it |
|
4352 |
continue; |
|
4353 |
} |
|
4354 |
k = idx; |
|
4355 |
} |
|
4356 | 4343 |
|
4357 | 4344 |
// Substitution placeholders may have been reordered if this |
4358 | 4345 |
// statement was rewritten by the HQL preprocessor. Make sure |
4359 | 4346 |
// we access the correct substitution parameter. |
4360 |
Object next = values[k]; |
|
4347 |
Function<Object[], Object> currentParameterFunction = pi.getIndex(j); |
|
4348 |
Object next = currentParameterFunction.apply(values); |
|
4361 | 4349 |
|
4362 | 4350 |
// store parameters in the base args array, resolving them first if necessary |
4363 | 4351 |
if (next instanceof Resolvable) |
new/src/com/goldencode/p2j/persist/RecordBuffer.java 2023-02-09 11:41:45 +0000 | ||
---|---|---|
1265 | 1265 |
** runtime. |
1266 | 1266 |
** CA 20230123 isPropertyIndexed must have protected access, because is accessed from static |
1267 | 1267 |
** methods. |
1268 |
** DDF 20230209 Refactoring ParameterIndices into ParameterDiff and added method for retrieving |
|
1269 |
** parameter values. (refs: #7035) |
|
1268 | 1270 |
*/ |
1269 | 1271 | |
1270 | 1272 |
/* |
... | ... | |
10743 | 10745 |
|
10744 | 10746 |
if (args != null && args.length > 0) |
10745 | 10747 |
{ |
10746 |
ParameterIndices pi = preproc.getParameterIndices(); |
|
10747 |
int len = pi.getCount(); |
|
10748 |
List<Object> argList = new ArrayList<>(len); |
|
10749 |
for (int i = 0, count = 0; count < len; i++) |
|
10750 |
{ |
|
10751 |
Integer nextIndex = pi.getIndex(i); |
|
10752 |
if (nextIndex == null) |
|
10753 |
{ |
|
10754 |
// original substitution parameter was inlined into HQL by preprocessor; |
|
10755 |
// skip it. |
|
10756 |
continue; |
|
10757 |
} |
|
10758 |
|
|
10759 |
// substitution placeholders may have been reordered if this statement was |
|
10760 |
// rewritten by the HQL preprocessor; make sure we access the correct |
|
10761 |
// substitution parameter |
|
10762 |
Object next = args[nextIndex]; |
|
10763 |
argList.add(next); |
|
10764 |
|
|
10765 |
count++; |
|
10766 |
} |
|
10767 |
args = argList.toArray(); |
|
10748 |
ParameterDiff pd = preproc.getParameterDiff(); |
|
10749 |
Object[] filteredArgs = pd.getSubstParameters(args); |
|
10750 |
args = filteredArgs; |
|
10768 | 10751 |
} |
10769 | 10752 |
} |
10770 | 10753 |
|
new/src/com/goldencode/p2j/persist/TemporaryBuffer.java 2023-02-09 11:42:37 +0000 | ||
---|---|---|
645 | 645 |
** runtime. |
646 | 646 |
** HC 20230118 Eliminated some of the uses of String.toUpperCase and/or |
647 | 647 |
** String.toLowerCase for performance. |
648 |
** DDF 20230209 Refactoring ParameterIndices into ParameterDiff and added method for retrieving |
|
649 |
** parameter values. (refs: #7035) |
|
648 | 650 |
*/ |
649 | 651 | |
650 | 652 |
/* |
... | ... | |
7856 | 7858 |
|
7857 | 7859 |
if (args != null && args.length > 0) |
7858 | 7860 |
{ |
7859 |
ParameterIndices pi = preproc.getParameterIndices(); |
|
7860 |
int len = pi.getCount(); |
|
7861 |
List<Object> argList = new ArrayList<>(len); |
|
7862 |
for (int i = 0, count = 0; count < len; i++) |
|
7863 |
{ |
|
7864 |
Integer nextIndex = pi.getIndex(i); |
|
7865 |
if (nextIndex == null) |
|
7866 |
{ |
|
7867 |
// original substitution parameter was inlined into HQL by preprocessor; |
|
7868 |
// skip it. |
|
7869 |
continue; |
|
7870 |
} |
|
7871 |
|
|
7872 |
// substitution placeholders may have been reordered if this statement was |
|
7873 |
// rewritten by the HQL preprocessor; make sure we access the correct |
|
7874 |
// substitution parameter |
|
7875 |
Object next = args[nextIndex]; |
|
7876 |
argList.add(next); |
|
7877 |
|
|
7878 |
count++; |
|
7879 |
} |
|
7880 |
args = argList.toArray(); |
|
7861 |
ParameterDiff pd = preproc.getParameterDiff(); |
|
7862 |
Object[] filteredArgs = pd.getSubstParameters(args); |
|
7863 |
args = filteredArgs; |
|
7881 | 7864 |
} |
7882 | 7865 |
} |
7883 | 7866 |
String delStmt = query.toFinalExpression(); |
new/src/com/goldencode/p2j/persist/orm/TempTableDataSourceProvider.java 2023-02-09 11:24:29 +0000 | ||
---|---|---|
79 | 79 |
import java.util.logging.*; |
80 | 80 |
import javax.sql.DataSource; |
81 | 81 |
import com.goldencode.cache.*; |
82 |
import com.goldencode.p2j.jmx.*; |
|
82 | 83 |
import com.goldencode.p2j.persist.*; |
83 | 84 |
import com.goldencode.p2j.persist.dialect.*; |
84 | 85 |
import com.goldencode.p2j.persist.orm.types.*; |
... | ... | |
120 | 121 |
/** Logger */ |
121 | 122 |
private static final Logger LOG = LogHelper.getLogger(DataSourceImpl.class.getName()); |
122 | 123 |
|
124 |
private static final SimpleCounter PSCacheHits = SimpleCounter.getInstance( |
|
125 |
FwdJMX.Counter.PSCacheHits |
|
126 |
); |
|
127 |
|
|
128 |
private static final SimpleCounter PSCacheMisses = SimpleCounter.getInstance( |
|
129 |
FwdJMX.Counter.PSCacheMisses |
|
130 |
); |
|
131 |
|
|
123 | 132 |
/** |
124 | 133 |
* Attempts to establish a connection with the data source of the {@code _temp} database. |
125 | 134 |
* Uses the credentials from the {@code DatabaseManager} configuration. |
... | ... | |
231 | 240 |
PreparedStatement raw = ctx.physicalConn.prepareStatement(sql, resultSetType, resultSetConcurrency); |
232 | 241 |
ps = new UnclosablePreparedStatement(raw, false); |
233 | 242 |
ctx.psCache.put(key, ps); |
243 |
PSCacheMisses.update(1L); |
|
234 | 244 |
} |
235 | 245 |
else if (ps.isCheckedOut()) |
236 | 246 |
{ |
... | ... | |
243 | 253 |
{ |
244 | 254 |
LOG.log(Level.FINE, "Multiply-cached PreparedStatement: " + sql); |
245 | 255 |
} |
256 |
PSCacheMisses.update(1L); |
|
257 |
} |
|
258 |
else |
|
259 |
{ |
|
260 |
PSCacheHits.update(1L); |
|
246 | 261 |
} |
247 | 262 |
|
248 | 263 |
ps.checkOut(); |