use of com.orientechnologies.orient.core.sql.functions.OSQLFunctionRuntime in project orientdb by orientechnologies.
the class OSQLFilterCondition method evaluate.
protected Object evaluate(OIdentifiable iCurrentRecord, final ODocument iCurrentResult, final Object iValue, final OCommandContext iContext, final boolean binaryEvaluation) {
if (iValue == null)
return null;
if (iValue instanceof BytesContainer)
return iValue;
if (iCurrentRecord != null) {
iCurrentRecord = iCurrentRecord.getRecord();
if (iCurrentRecord != null && ((ORecord) iCurrentRecord).getInternalStatus() == ORecordElement.STATUS.NOT_LOADED) {
try {
iCurrentRecord = iCurrentRecord.getRecord().load();
} catch (ORecordNotFoundException e) {
return null;
}
}
}
if (binaryEvaluation && iValue instanceof OSQLFilterItemField) {
final OBinaryField bField = ((OSQLFilterItemField) iValue).getBinaryField(iCurrentRecord);
if (bField != null)
return bField;
}
if (iValue instanceof OSQLFilterItem) {
return ((OSQLFilterItem) iValue).getValue(iCurrentRecord, iCurrentResult, iContext);
}
if (iValue instanceof OSQLFilterCondition) {
// NESTED CONDITION: EVALUATE IT RECURSIVELY
return ((OSQLFilterCondition) iValue).evaluate(iCurrentRecord, iCurrentResult, iContext);
}
if (iValue instanceof OSQLFunctionRuntime) {
// STATELESS FUNCTION: EXECUTE IT
final OSQLFunctionRuntime f = (OSQLFunctionRuntime) iValue;
return f.execute(iCurrentRecord, iCurrentRecord, iCurrentResult, iContext);
}
if (OMultiValue.isMultiValue(iValue)) {
final Iterable<?> multiValue = OMultiValue.getMultiValueIterable(iValue, false);
// MULTI VALUE: RETURN A COPY
final ArrayList<Object> result = new ArrayList<Object>(OMultiValue.getSize(iValue));
for (final Object value : multiValue) {
if (value instanceof OSQLFilterItem) {
result.add(((OSQLFilterItem) value).getValue(iCurrentRecord, iCurrentResult, iContext));
} else {
result.add(value);
}
}
return result;
}
// SIMPLE VALUE: JUST RETURN IT
return iValue;
}
use of com.orientechnologies.orient.core.sql.functions.OSQLFunctionRuntime in project orientdb by orientechnologies.
the class OCommandExecutorSQLResultsetAbstract method optimizeBranch.
protected void optimizeBranch(final OSQLFilterCondition iParentCondition, OSQLFilterCondition iCondition) {
if (iCondition == null)
return;
Object left = iCondition.getLeft();
if (left instanceof OSQLFilterCondition) {
// ANALYSE LEFT RECURSIVELY
optimizeBranch(iCondition, (OSQLFilterCondition) left);
} else if (left instanceof OSQLFunctionRuntime) {
left = optimizeFunction((OSQLFunctionRuntime) left);
iCondition.setLeft(left);
}
Object right = iCondition.getRight();
if (right instanceof OSQLFilterCondition) {
// ANALYSE RIGHT RECURSIVELY
optimizeBranch(iCondition, (OSQLFilterCondition) right);
} else if (right instanceof OSQLFunctionRuntime) {
right = optimizeFunction((OSQLFunctionRuntime) right);
iCondition.setRight(right);
}
final OQueryOperator oper = iCondition.getOperator();
Object result = null;
if (left instanceof OSQLFilterItemField && right instanceof OSQLFilterItemField) {
if (((OSQLFilterItemField) left).getRoot().equals(((OSQLFilterItemField) right).getRoot())) {
if (oper instanceof OQueryOperatorEquals)
result = Boolean.TRUE;
else if ((oper instanceof OQueryOperatorNotEquals) || (oper instanceof OQueryOperatorNotEquals2))
result = Boolean.FALSE;
}
}
if (result != null) {
if (iParentCondition != null)
if (iCondition == iParentCondition.getLeft())
// REPLACE LEFT
iCondition.setLeft(result);
else
// REPLACE RIGHT
iCondition.setRight(result);
else {
// REPLACE ROOT CONDITION
if (result instanceof Boolean && ((Boolean) result))
compiledFilter.setRootCondition(null);
}
}
}
use of com.orientechnologies.orient.core.sql.functions.OSQLFunctionRuntime in project orientdb by orientechnologies.
the class OCommandExecutorSQLSelect method searchForIndexes.
@SuppressWarnings("rawtypes")
private boolean searchForIndexes(final OClass iSchemaClass) {
if (uniqueResult != null)
uniqueResult.clear();
final ODatabaseDocument database = getDatabase();
database.checkSecurity(ORule.ResourceGeneric.CLASS, ORole.PERMISSION_READ, iSchemaClass.getName().toLowerCase());
// fetch all possible variants of subqueries that can be used in indexes.
if (compiledFilter == null) {
return tryOptimizeSort(iSchemaClass);
}
// try indexed functions
Iterator<OIdentifiable> fetchedFromFunction = tryIndexedFunctions(iSchemaClass);
if (fetchedFromFunction != null) {
fetchFromTarget(fetchedFromFunction);
return true;
}
// the main condition is a set of sub-conditions separated by OR operators
final List<List<OIndexSearchResult>> conditionHierarchy = filterAnalyzer.analyzeMainCondition(compiledFilter.getRootCondition(), iSchemaClass, context);
if (conditionHierarchy == null)
return false;
List<OIndexCursor> cursors = new ArrayList<OIndexCursor>();
boolean indexIsUsedInOrderBy = false;
List<IndexUsageLog> indexUseAttempts = new ArrayList<IndexUsageLog>();
try {
//to track if the index used is specific for this class or if it's defined on a super/sub class
boolean indexOnExactClass = true;
OIndexSearchResult lastSearchResult = null;
for (List<OIndexSearchResult> indexSearchResults : conditionHierarchy) {
// go through all variants to choose which one can be used for index search.
boolean indexUsed = false;
for (final OIndexSearchResult searchResult : indexSearchResults) {
lastSearchResult = searchResult;
final List<OIndex<?>> involvedIndexes = filterAnalyzer.getInvolvedIndexes(iSchemaClass, searchResult);
Collections.sort(involvedIndexes, new IndexComparator());
indexOnExactClass = true;
// go through all possible index for given set of fields.
for (final OIndex index : involvedIndexes) {
final long indexRebuildVersion = index.getRebuildVersion();
if (index.isRebuilding()) {
continue;
}
final OIndexDefinition indexDefinition = index.getDefinition();
if (searchResult.containsNullValues && indexDefinition.isNullValuesIgnored()) {
continue;
}
final OQueryOperator operator = searchResult.lastOperator;
// are equals.
if (!OIndexSearchResult.isIndexEqualityOperator(operator)) {
final String lastFiled = searchResult.lastField.getItemName(searchResult.lastField.getItemCount() - 1);
final String relatedIndexField = indexDefinition.getFields().get(searchResult.fieldValuePairs.size());
if (!lastFiled.equals(relatedIndexField)) {
continue;
}
}
final int searchResultFieldsCount = searchResult.fields().size();
final List<Object> keyParams = new ArrayList<Object>(searchResultFieldsCount);
// We get only subset contained in processed sub query.
for (final String fieldName : indexDefinition.getFields().subList(0, searchResultFieldsCount)) {
Object fieldValue = searchResult.fieldValuePairs.get(fieldName);
if (fieldValue instanceof OSQLQuery<?> || fieldValue instanceof OSQLFilterCondition) {
return false;
}
if (fieldValue != null) {
keyParams.add(fieldValue);
} else {
if (searchResult.lastValue instanceof OSQLQuery<?> || searchResult.lastValue instanceof OSQLFilterCondition) {
return false;
}
keyParams.add(searchResult.lastValue);
}
}
metricRecorder.recordInvolvedIndexesMetric(index);
OIndexCursor cursor;
indexIsUsedInOrderBy = orderByOptimizer.canBeUsedByOrderByAfterFilter(index, getEqualsClausesPrefix(searchResult), orderedFields) && !(index.getInternal() instanceof OChainedIndexProxy);
try {
boolean ascSortOrder = !indexIsUsedInOrderBy || orderedFields.get(0).getValue().equals(KEYWORD_ASC);
if (indexIsUsedInOrderBy) {
fullySortedByIndex = expandTarget == null && indexDefinition.getFields().size() >= orderedFields.size() && conditionHierarchy.size() == 1;
}
context.setVariable("$limit", limit);
cursor = operator.executeIndexQuery(context, index, keyParams, ascSortOrder);
if (!iSchemaClass.getName().equals(index.getDefinition().getClassName())) {
indexOnExactClass = false;
}
} catch (OIndexEngineException e) {
throw e;
} catch (Exception e) {
OLogManager.instance().error(this, "Error on using index %s in query '%s'. Probably you need to rebuild indexes. Now executing query using cluster scan", e, index.getName(), request != null && request.getText() != null ? request.getText() : "");
fullySortedByIndex = false;
cursors.clear();
return false;
}
if (cursor == null) {
continue;
}
if (index.getRebuildVersion() == indexRebuildVersion) {
cursors.add(OIndexChangesWrapper.wrap(index, cursor, indexRebuildVersion));
indexUseAttempts.add(new IndexUsageLog(index, keyParams, indexDefinition));
indexUsed = true;
break;
}
}
if (indexUsed) {
break;
}
}
if (!indexUsed) {
return tryOptimizeSort(iSchemaClass);
}
}
if (cursors.size() == 0 || lastSearchResult == null) {
return false;
}
if (cursors.size() == 1 && canOptimize(conditionHierarchy)) {
filterOptimizer.optimize(compiledFilter, lastSearchResult);
}
uniqueResult = new ConcurrentHashMap<ORID, ORID>();
if (cursors.size() == 1 && (compiledFilter == null || compiledFilter.getRootCondition() == null) && groupByFields == null && projections != null && projections.size() == 1) {
// OPTIMIZATION: ONE INDEX USED WITH JUST ONE CONDITION: REMOVE THE FILTER
final Entry<String, Object> entry = projections.entrySet().iterator().next();
if (entry.getValue() instanceof OSQLFunctionRuntime) {
final OSQLFunctionRuntime rf = (OSQLFunctionRuntime) entry.getValue();
if (rf.function instanceof OSQLFunctionCount && rf.configuredParameters.length == 1 && "*".equals(rf.configuredParameters[0])) {
final boolean restrictedClasses = isUsingRestrictedClasses();
if (!restrictedClasses && indexOnExactClass) {
final OIndexCursor cursor = cursors.get(0);
long count = 0;
if (cursor instanceof OSizeable)
count = ((OSizeable) cursor).size();
else {
while (cursor.hasNext()) {
cursor.next();
count++;
}
}
final OProfiler profiler = Orient.instance().getProfiler();
if (profiler.isRecording()) {
profiler.updateCounter(profiler.getDatabaseMetric(database.getName(), "query.indexUsed"), "Used index in query", +1);
}
if (tempResult == null)
tempResult = new ArrayList<OIdentifiable>();
((Collection<OIdentifiable>) tempResult).add(new ODocument().field(entry.getKey(), count));
return true;
}
}
}
}
for (OIndexCursor cursor : cursors) {
if (!fetchValuesFromIndexCursor(cursor)) {
break;
}
}
uniqueResult.clear();
uniqueResult = null;
metricRecorder.recordOrderByOptimizationMetric(indexIsUsedInOrderBy, this.fullySortedByIndex);
indexUseAttempts.clear();
return true;
} finally {
for (IndexUsageLog wastedIndexUsage : indexUseAttempts) {
revertProfiler(context, wastedIndexUsage.index, wastedIndexUsage.keyParams, wastedIndexUsage.indexDefinition);
}
}
}
use of com.orientechnologies.orient.core.sql.functions.OSQLFunctionRuntime in project orientdb by orientechnologies.
the class ORuntimeResult method applyRecord.
@SuppressWarnings("unchecked")
public static ODocument applyRecord(final ODocument iValue, final Map<String, Object> iProjections, final OCommandContext iContext, final OIdentifiable iRecord) {
// APPLY PROJECTIONS
ORecord record = (iRecord != null ? iRecord.getRecord() : null);
//MANAGE SPECIFIC CASES FOR RECORD BYTES
if (ORecordBytes.RECORD_TYPE == ORecordInternal.getRecordType(record)) {
for (Entry<String, Object> projection : iProjections.entrySet()) {
if ("@rid".equalsIgnoreCase("" + projection.getValue())) {
iValue.field(projection.getKey(), record.getIdentity());
} else if ("@size".equalsIgnoreCase("" + projection.getValue())) {
iValue.field(projection.getKey(), record.getSize());
} else if ("@version".equalsIgnoreCase("" + projection.getValue())) {
iValue.field(projection.getKey(), record.getVersion());
} else {
Object val = projection.getValue();
if (val instanceof Number || val instanceof String || val instanceof Boolean) {
iValue.field(projection.getKey(), val);
} else {
iValue.field(projection.getKey(), (Object) null);
}
}
}
return iValue;
}
final ODocument inputDocument = (ODocument) record;
if (iProjections.isEmpty())
// SELECT * CASE
inputDocument.copyTo(iValue);
else {
for (Entry<String, Object> projection : iProjections.entrySet()) {
final String prjName = projection.getKey();
final Object v = projection.getValue();
if (v == null && prjName != null) {
iValue.field(prjName, (Object) null);
continue;
}
final Object projectionValue;
if (v != null && v.equals("*")) {
// COPY ALL
inputDocument.copyTo(iValue);
// CONTINUE WITH NEXT ITEM
continue;
} else if (v instanceof OSQLFilterItemVariable || v instanceof OSQLFilterItemField) {
final OSQLFilterItemAbstract var = (OSQLFilterItemAbstract) v;
final OPair<OSQLMethodRuntime, Object[]> last = var.getLastChainOperator();
if (last != null && last.getKey().getMethod() instanceof OSQLMethodField && last.getValue() != null && last.getValue().length == 1 && last.getValue()[0].equals("*")) {
final Object value = ((OSQLFilterItemAbstract) v).getValue(inputDocument, iValue, iContext);
if (inputDocument != null && value != null && inputDocument instanceof ODocument && value instanceof ODocument) {
// COPY FIELDS WITH PROJECTION NAME AS PREFIX
for (String fieldName : ((ODocument) value).fieldNames()) {
iValue.field(prjName + fieldName, ((ODocument) value).field(fieldName));
}
}
projectionValue = null;
} else
// RETURN A VARIABLE FROM THE CONTEXT
projectionValue = ((OSQLFilterItemAbstract) v).getValue(inputDocument, iValue, iContext);
} else if (v instanceof OSQLFunctionRuntime) {
final OSQLFunctionRuntime f = (OSQLFunctionRuntime) v;
projectionValue = f.execute(inputDocument, inputDocument, iValue, iContext);
} else {
if (v == null) {
// SIMPLE NULL VALUE: SET IT IN DOCUMENT
iValue.field(prjName, v);
continue;
}
projectionValue = v;
}
if (projectionValue != null)
if (projectionValue instanceof ORidBag)
iValue.field(prjName, new ORidBag((ORidBag) projectionValue));
else if (projectionValue instanceof OIdentifiable && !(projectionValue instanceof ORID) && !(projectionValue instanceof ORecord))
iValue.field(prjName, ((OIdentifiable) projectionValue).getRecord());
else if (projectionValue instanceof Iterator) {
boolean link = true;
// make temporary value typical case graph database elemenet's iterator edges
if (projectionValue instanceof OResettable)
((OResettable) projectionValue).reset();
final List<Object> iteratorValues = new ArrayList<Object>();
final Iterator projectionValueIterator = (Iterator) projectionValue;
while (projectionValueIterator.hasNext()) {
Object value = projectionValueIterator.next();
if (value instanceof OIdentifiable) {
value = ((OIdentifiable) value).getRecord();
if (value != null && !((OIdentifiable) value).getIdentity().isPersistent())
link = false;
}
if (value != null)
iteratorValues.add(value);
}
iValue.field(prjName, iteratorValues, link ? OType.LINKLIST : OType.EMBEDDEDLIST);
} else if (projectionValue instanceof ODocument && !((ODocument) projectionValue).getIdentity().isPersistent()) {
iValue.field(prjName, projectionValue, OType.EMBEDDED);
} else if (projectionValue instanceof Set<?>) {
OType type = OType.getTypeByValue(projectionValue);
if (type == OType.LINKSET && !entriesPersistent((Collection<OIdentifiable>) projectionValue))
type = OType.EMBEDDEDSET;
iValue.field(prjName, projectionValue, type);
} else if (projectionValue instanceof Map<?, ?>) {
OType type = OType.getTypeByValue(projectionValue);
if (type == OType.LINKMAP && !entriesPersistent(((Map<?, OIdentifiable>) projectionValue).values()))
type = OType.EMBEDDEDMAP;
iValue.field(prjName, projectionValue, type);
} else if (projectionValue instanceof List<?>) {
OType type = OType.getTypeByValue(projectionValue);
if (type == OType.LINKLIST && !entriesPersistent((Collection<OIdentifiable>) projectionValue))
type = OType.EMBEDDEDLIST;
iValue.field(prjName, projectionValue, type);
} else
iValue.field(prjName, projectionValue);
}
}
return iValue;
}
use of com.orientechnologies.orient.core.sql.functions.OSQLFunctionRuntime in project orientdb by orientechnologies.
the class OCommandExecutorSQLSelect method isIndexKeySizeQuery.
private boolean isIndexKeySizeQuery() {
if (!(aggregate && projections.entrySet().size() == 1)) {
return false;
}
final Object projection = projections.values().iterator().next();
if (!(projection instanceof OSQLFunctionRuntime)) {
return false;
}
final OSQLFunctionRuntime f = (OSQLFunctionRuntime) projection;
if (!f.getRoot().equals(OSQLFunctionCount.NAME)) {
return false;
}
if (!(f.configuredParameters != null && f.configuredParameters.length == 1 && f.configuredParameters[0] instanceof OSQLFunctionRuntime)) {
return false;
}
final OSQLFunctionRuntime fConfigured = (OSQLFunctionRuntime) f.configuredParameters[0];
if (!fConfigured.getRoot().equals(OSQLFunctionDistinct.NAME)) {
return false;
}
if (!(fConfigured.configuredParameters != null && fConfigured.configuredParameters.length == 1 && fConfigured.configuredParameters[0] instanceof OSQLFilterItemField)) {
return false;
}
final OSQLFilterItemField field = (OSQLFilterItemField) fConfigured.configuredParameters[0];
return field.getRoot().equals("key");
}
Aggregations