98 |
98 |
** AL2 20220706 Added isCompatible to filter out the sort clauses not belonging to the buffer.
|
99 |
99 |
** OM 20220727 FieldId and PropertyId are different for denormalized extent fields.
|
100 |
100 |
** OM 20221103 New class names for FQLPreprocessor, FQLExpression, FQLBundle, and FQLCache.
|
|
101 |
** RAA 20230110 Reduced the number of iterations (for parsing the text) in constructor. Made
|
|
102 |
** all non-final fields final.
|
101 |
103 |
*/
|
102 |
104 |
|
103 |
105 |
/*
|
... | ... | |
253 |
255 |
private final String originalName;
|
254 |
256 |
|
255 |
257 |
/** Sort property name, usually qualified */
|
256 |
|
private String name;
|
|
258 |
private final String name;
|
257 |
259 |
|
258 |
260 |
/** Subscript value, if any */
|
259 |
|
private int subscript = -1;
|
|
261 |
private final int subscript;
|
260 |
262 |
|
261 |
263 |
/** SQL dialect which used this sort criterion; used for rtrim calls on character properties */
|
262 |
|
private Dialect dialect = null;
|
|
264 |
private final Dialect dialect;
|
263 |
265 |
|
264 |
266 |
/**
|
265 |
267 |
* Constructor which parses original sort component text, deriving the property name, sort
|
... | ... | |
344 |
346 |
this.dialect = dialect;
|
345 |
347 |
this.dmoClass = dmoInfo.getImplementationClass();
|
346 |
348 |
|
347 |
|
// parse the test and extract alias, property and optional extent
|
348 |
|
int spacePos = text.indexOf(' ');
|
349 |
|
String rawName = ((spacePos != -1) ? text.substring(0, spacePos) : text).trim();
|
350 |
|
name = rawName;
|
351 |
|
originalName = internStrings ? rawName.intern() : rawName;
|
352 |
|
int bracketPos = rawName.indexOf("[");
|
353 |
|
int endPos = -1;
|
354 |
|
if (bracketPos >= 0)
|
|
349 |
char[] src = text.toCharArray();
|
|
350 |
int srcLength = src.length;
|
|
351 |
boolean extentMode = false;
|
|
352 |
|
|
353 |
// initially, this is set to the end-of-line position because we might not have a space.
|
|
354 |
int spacePos = srcLength;
|
|
355 |
int dotPos = -1;
|
|
356 |
int bracketPos = -1;
|
|
357 |
boolean reachedBracket = false;
|
|
358 |
int subscriptBuilder = 0;
|
|
359 |
|
|
360 |
for (int i = 0; i < srcLength; i++)
|
355 |
361 |
{
|
356 |
|
endPos = rawName.indexOf("]");
|
357 |
|
if (endPos < 0)
|
|
362 |
switch (src[i])
|
358 |
363 |
{
|
359 |
|
throw new PersistenceException("Malformed subscript text: " + text);
|
|
364 |
case '[':
|
|
365 |
{
|
|
366 |
extentMode = true;
|
|
367 |
reachedBracket = true;
|
|
368 |
bracketPos = i;
|
|
369 |
break;
|
|
370 |
}
|
|
371 |
case ']':
|
|
372 |
{
|
|
373 |
extentMode = false;
|
|
374 |
break;
|
|
375 |
}
|
|
376 |
case '.':
|
|
377 |
{
|
|
378 |
dotPos = i;
|
|
379 |
break;
|
|
380 |
}
|
|
381 |
case ' ':
|
|
382 |
{
|
|
383 |
spacePos = i;
|
|
384 |
break;
|
|
385 |
}
|
360 |
386 |
}
|
361 |
387 |
|
362 |
|
// extract base name
|
363 |
|
name = rawName.substring(0, bracketPos);
|
364 |
|
}
|
365 |
|
|
366 |
|
int dotPos = name.lastIndexOf(".");
|
367 |
|
if (dotPos < 0)
|
368 |
|
{
|
369 |
|
throw new PersistenceException("Sort property may not be unqualified: " + rawName);
|
370 |
|
}
|
371 |
|
|
372 |
|
String propName = name.substring(dotPos + 1);
|
373 |
|
String alias = name.substring(0, dotPos);
|
|
388 |
if (extentMode && src[i] != '[')
|
|
389 |
{
|
|
390 |
subscriptBuilder = subscriptBuilder * 10 + (src[i] - '0');
|
|
391 |
}
|
|
392 |
}
|
|
393 |
|
|
394 |
originalName = internStrings ? new String(src, 0, spacePos).intern() :
|
|
395 |
new String(src, 0, spacePos);
|
|
396 |
int length = (reachedBracket ? Math.min(bracketPos, spacePos) : spacePos) - dotPos - 1;
|
|
397 |
propertyName = internStrings ?
|
|
398 |
new String(src, dotPos + 1, length).intern() :
|
|
399 |
new String(src, dotPos + 1, length);
|
|
400 |
alias = internStrings ? new String(src, 0, dotPos).intern() :
|
|
401 |
new String(src, 0, dotPos);
|
|
402 |
name = internStrings ? new String(src, 0, dotPos + propertyName.length() + 1).intern() :
|
|
403 |
new String(src, 0, dotPos + propertyName.length() + 1);
|
|
404 |
subscript = reachedBracket ? subscriptBuilder : -1;
|
|
405 |
|
|
406 |
// if no space is found, then "asc" is implicit or
|
|
407 |
// if the first character after the space is 'a', then "asc" is explicit;
|
|
408 |
// otherwise, "desc" is found after the space.
|
|
409 |
ascending = spacePos == srcLength || src[spacePos + 1] == 'a';
|
|
410 |
|
374 |
411 |
DmoMeta dmoMeta = DmoMetadataManager.getDmoInfo(dmoClass);
|
375 |
|
Property propMeta = dmoMeta.getFieldInfo(propName);
|
376 |
|
this.propertyName = propMeta.name; // already interned, anyway
|
377 |
|
this.alias = internStrings ? alias.intern() : alias;
|
378 |
|
|
379 |
|
if (bracketPos >= 0)
|
380 |
|
{
|
381 |
|
int extent = propMeta.index > 0 ? 0 : propMeta.extent;
|
382 |
|
if (extent > 0)
|
383 |
|
{
|
384 |
|
// extract subscript
|
385 |
|
String sub = rawName.substring(bracketPos + 1, endPos);
|
386 |
|
try
|
387 |
|
{
|
388 |
|
subscript = Integer.parseInt(sub);
|
389 |
|
}
|
390 |
|
catch (NumberFormatException exc)
|
391 |
|
{
|
392 |
|
throw new PersistenceException("Unsupported subscript: " + sub);
|
393 |
|
}
|
394 |
|
|
395 |
|
name = alias + "." + propertyName;
|
396 |
|
}
|
397 |
|
}
|
398 |
|
|
399 |
|
if (internStrings)
|
400 |
|
{
|
401 |
|
name = name.intern();
|
402 |
|
}
|
403 |
|
|
404 |
|
// determine sort direction
|
405 |
|
ascending = (spacePos == -1 || !"desc".equalsIgnoreCase(text.substring(spacePos + 1).trim()));
|
|
412 |
Property propMeta = dmoMeta.getFieldInfo(propertyName);
|
406 |
413 |
|
407 |
414 |
// get backing getter method
|
408 |
415 |
if (propMeta.propId == ReservedProperty.ID_MULTIPLEX)
|