use of com.orientechnologies.orient.core.exception.OCommandExecutionException in project orientdb by orientechnologies.
the class OMatchStatement method expandCartesianProduct.
private boolean expandCartesianProduct(Pattern pattern, MatchContext matchContext, Map<String, String> aliasClasses, Map<String, OWhereClause> aliasFilters, OCommandContext iCommandContext, OSQLAsynchQuery<ODocument> request) {
for (String alias : pattern.aliasToNode.keySet()) {
if (!matchContext.matched.containsKey(alias)) {
String target = aliasClasses.get(alias);
if (target == null) {
throw new OCommandExecutionException("Cannot execute MATCH statement on alias " + alias + ": class not defined");
}
Iterable<OIdentifiable> values = fetchAliasCandidates(alias, aliasFilters, iCommandContext, aliasClasses);
for (OIdentifiable id : values) {
MatchContext childContext = matchContext.copy(alias, id);
if (allNodesCalculated(childContext, pattern)) {
// false if limit reached
boolean added = addResult(childContext, request, iCommandContext);
if (!added) {
return false;
}
} else {
// false if limit reached
boolean added = expandCartesianProduct(pattern, childContext, aliasClasses, aliasFilters, iCommandContext, request);
if (!added) {
return false;
}
}
}
break;
}
}
return true;
}
use of com.orientechnologies.orient.core.exception.OCommandExecutionException in project orientdb by orientechnologies.
the class OMatchStatement method estimateRootEntries.
private Map<String, Long> estimateRootEntries(Map<String, String> aliasClasses, Map<String, OWhereClause> aliasFilters, OCommandContext ctx) {
Set<String> allAliases = new LinkedHashSet<String>();
allAliases.addAll(aliasClasses.keySet());
allAliases.addAll(aliasFilters.keySet());
OSchema schema = getDatabase().getMetadata().getSchema();
Map<String, Long> result = new LinkedHashMap<String, Long>();
for (String alias : allAliases) {
if (this.pattern.aliasToNode.get(alias).isOptionalNode()) {
continue;
}
String className = aliasClasses.get(alias);
if (className == null) {
continue;
}
if (!schema.existsClass(className)) {
throw new OCommandExecutionException("class not defined: " + className);
}
OClass oClass = schema.getClass(className);
long upperBound;
OWhereClause filter = aliasFilters.get(alias);
if (filter != null) {
List<String> aliasesOnPattern = filter.baseExpression.getMatchPatternInvolvedAliases();
if (aliasesOnPattern != null && aliasesOnPattern.size() > 0) {
//skip root nodes that have a condition on $matched, because they have to be calculated as downstream
continue;
}
upperBound = filter.estimate(oClass, this.threshold, ctx);
} else {
upperBound = oClass.count();
}
result.put(alias, upperBound);
}
return result;
}
use of com.orientechnologies.orient.core.exception.OCommandExecutionException in project orientdb by orientechnologies.
the class OCommandExecutorSQLSelect method applyExpand.
/**
* Extract the content of collections and/or links and put it as result
*/
private void applyExpand() {
if (expandTarget == null) {
return;
}
final long startExpand = System.currentTimeMillis();
try {
if (tempResult == null) {
tempResult = new ArrayList<OIdentifiable>();
if (expandTarget instanceof OSQLFilterItemVariable) {
Object r = ((OSQLFilterItemVariable) expandTarget).getValue(null, null, context);
if (r != null) {
if (r instanceof OIdentifiable) {
((Collection<OIdentifiable>) tempResult).add((OIdentifiable) r);
} else if (r instanceof Iterator || OMultiValue.isMultiValue(r)) {
for (Object o : OMultiValue.getMultiValueIterable(r)) {
((Collection<OIdentifiable>) tempResult).add((OIdentifiable) o);
}
}
}
} else if (expandTarget instanceof OSQLFunctionRuntime && !hasFieldItemParams((OSQLFunctionRuntime) expandTarget)) {
if (((OSQLFunctionRuntime) expandTarget).aggregateResults()) {
throw new OCommandExecutionException("Unsupported operation: aggregate function in expand(" + expandTarget + ")");
} else {
Object r = ((OSQLFunctionRuntime) expandTarget).execute(null, null, null, context);
if (r instanceof OIdentifiable) {
((Collection<OIdentifiable>) tempResult).add((OIdentifiable) r);
} else if (r instanceof Iterator || OMultiValue.isMultiValue(r)) {
int i = 0;
for (Object o : OMultiValue.getMultiValueIterable(r)) {
if ((++i) % 100 == 0 && !checkInterruption()) {
return;
}
((Collection<OIdentifiable>) tempResult).add((OIdentifiable) o);
}
}
}
}
} else {
if (tempResult == null) {
tempResult = new ArrayList<OIdentifiable>();
}
final OMultiCollectionIterator<OIdentifiable> finalResult = new OMultiCollectionIterator<OIdentifiable>();
if (orderedFields == null || orderedFields.size() == 0) {
// expand is applied before sorting, so limiting the result set here would give wrong results
int iteratorLimit = 0;
if (limit < 0) {
iteratorLimit = -1;
} else {
iteratorLimit += limit;
}
finalResult.setLimit(iteratorLimit);
finalResult.setSkip(skip);
}
for (OIdentifiable id : tempResult) {
if (!checkInterruption()) {
return;
}
final Object fieldValue;
if (expandTarget instanceof OSQLFilterItem) {
fieldValue = ((OSQLFilterItem) expandTarget).getValue(id.getRecord(), null, context);
} else if (expandTarget instanceof OSQLFunctionRuntime) {
fieldValue = ((OSQLFunctionRuntime) expandTarget).getResult();
} else {
fieldValue = expandTarget.toString();
}
if (fieldValue != null) {
if (fieldValue instanceof ODocument) {
ArrayList<ODocument> partial = new ArrayList<ODocument>();
partial.add((ODocument) fieldValue);
finalResult.add(partial);
} else if (fieldValue instanceof Collection<?> || fieldValue.getClass().isArray() || fieldValue instanceof Iterator<?> || fieldValue instanceof OIdentifiable || fieldValue instanceof ORidBag) {
finalResult.add(fieldValue);
} else if (fieldValue instanceof Map<?, ?>) {
finalResult.add(((Map<?, OIdentifiable>) fieldValue).values());
}
}
}
tempResult = finalResult;
}
} finally {
context.setVariable("expandElapsed", (System.currentTimeMillis() - startExpand));
}
}
use of com.orientechnologies.orient.core.exception.OCommandExecutionException in project orientdb by orientechnologies.
the class OCommandExecutorSQLSelect method execParallelWithPool.
private boolean execParallelWithPool(final ORecordIteratorClusters iTarget, final ODatabaseDocumentTx db) {
final int[] clusterIds = iTarget.getClusterIds();
// CREATE ONE THREAD PER CLUSTER
final int jobNumbers = clusterIds.length;
final List<Future<?>> jobs = new ArrayList<Future<?>>();
OLogManager.instance().debug(this, "Executing parallel query with strategy executors. clusterIds=%d, jobs=%d", clusterIds.length, jobNumbers);
final boolean[] results = new boolean[jobNumbers];
final OCommandContext[] contexts = new OCommandContext[jobNumbers];
final RuntimeException[] exceptions = new RuntimeException[jobNumbers];
parallelRunning = true;
final AtomicInteger runningJobs = new AtomicInteger(jobNumbers);
for (int i = 0; i < jobNumbers; ++i) {
final int current = i;
final Runnable job = new Runnable() {
@Override
public void run() {
try {
ODatabaseDocumentInternal localDatabase = null;
try {
exceptions[current] = null;
results[current] = true;
final OCommandContext threadContext = context.copy();
contexts[current] = threadContext;
localDatabase = db.copy();
localDatabase.activateOnCurrentThread();
// CREATE A SNAPSHOT TO AVOID DEADLOCKS
db.getMetadata().getSchema().makeSnapshot();
scanClusterWithIterator(localDatabase, threadContext, clusterIds[current], current, results);
} catch (RuntimeException t) {
exceptions[current] = t;
} finally {
runningJobs.decrementAndGet();
resultQueue.offer(PARALLEL_END_EXECUTION_THREAD);
if (localDatabase != null)
localDatabase.close();
}
} catch (Exception e) {
if (exceptions[current] == null) {
exceptions[current] = new RuntimeException(e);
}
e.printStackTrace();
}
}
};
jobs.add(Orient.instance().submit(job));
}
final int maxQueueSize = OGlobalConfiguration.QUERY_PARALLEL_RESULT_QUEUE_SIZE.getValueAsInteger() - 1;
boolean cancelQuery = false;
boolean tipProvided = false;
while (runningJobs.get() > 0 || !resultQueue.isEmpty()) {
try {
final AsyncResult result = resultQueue.take();
final int qSize = resultQueue.size();
if (!tipProvided && qSize >= maxQueueSize) {
OLogManager.instance().debug(this, "Parallel query '%s' has result queue full (size=%d), this could reduce concurrency level. Consider increasing queue size with setting: %s=<size>", parserText, maxQueueSize + 1, OGlobalConfiguration.QUERY_PARALLEL_RESULT_QUEUE_SIZE.getKey());
tipProvided = true;
}
if (OExecutionThreadLocal.isInterruptCurrentOperation())
throw new InterruptedException("Operation has been interrupted");
if (result != PARALLEL_END_EXECUTION_THREAD) {
if (!handleResult(result.record, result.context)) {
// STOP EXECUTORS
parallelRunning = false;
break;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
cancelQuery = true;
break;
}
}
parallelRunning = false;
if (cancelQuery) {
// CANCEL ALL THE RUNNING JOBS
for (int i = 0; i < jobs.size(); ++i) {
jobs.get(i).cancel(true);
}
} else {
// JOIN ALL THE JOBS
for (int i = 0; i < jobs.size(); ++i) {
try {
jobs.get(i).get();
context.merge(contexts[i]);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (final ExecutionException e) {
OLogManager.instance().error(this, "Error on executing parallel query", e);
throw OException.wrapException(new OCommandExecutionException("Error on executing parallel query"), e);
}
}
}
// CHECK FOR ANY EXCEPTION
for (int i = 0; i < jobNumbers; ++i) if (exceptions[i] != null)
throw exceptions[i];
for (int i = 0; i < jobNumbers; ++i) {
if (!results[i])
return false;
}
return true;
}
use of com.orientechnologies.orient.core.exception.OCommandExecutionException in project orientdb by orientechnologies.
the class OCommandExecutorSQLSelect method searchInIndex.
private void searchInIndex() {
final OIndex<Object> index = (OIndex<Object>) getDatabase().getMetadata().getIndexManager().getIndex(parsedTarget.getTargetIndex());
if (index == null) {
throw new OCommandExecutionException("Target index '" + parsedTarget.getTargetIndex() + "' not found");
}
boolean ascOrder = true;
if (!orderedFields.isEmpty()) {
if (orderedFields.size() != 1) {
throw new OCommandExecutionException("Index can be ordered only by key field");
}
final String fieldName = orderedFields.get(0).getKey();
if (!fieldName.equalsIgnoreCase("key")) {
throw new OCommandExecutionException("Index can be ordered only by key field");
}
final String order = orderedFields.get(0).getValue();
ascOrder = order.equalsIgnoreCase(KEYWORD_ASC);
}
// nothing was added yet, so index definition for manual index was not calculated
if (index.getDefinition() == null) {
return;
}
if (compiledFilter != null && compiledFilter.getRootCondition() != null) {
if (!"KEY".equalsIgnoreCase(compiledFilter.getRootCondition().getLeft().toString())) {
throw new OCommandExecutionException("'Key' field is required for queries against indexes");
}
final OQueryOperator indexOperator = compiledFilter.getRootCondition().getOperator();
if (indexOperator instanceof OQueryOperatorBetween) {
final Object[] values = (Object[]) compiledFilter.getRootCondition().getRight();
final OIndexCursor cursor = index.iterateEntriesBetween(getIndexKey(index.getDefinition(), values[0], context), true, getIndexKey(index.getDefinition(), values[2], context), true, ascOrder);
fetchEntriesFromIndexCursor(cursor);
} else if (indexOperator instanceof OQueryOperatorMajor) {
final Object value = compiledFilter.getRootCondition().getRight();
final OIndexCursor cursor = index.iterateEntriesMajor(getIndexKey(index.getDefinition(), value, context), false, ascOrder);
fetchEntriesFromIndexCursor(cursor);
} else if (indexOperator instanceof OQueryOperatorMajorEquals) {
final Object value = compiledFilter.getRootCondition().getRight();
final OIndexCursor cursor = index.iterateEntriesMajor(getIndexKey(index.getDefinition(), value, context), true, ascOrder);
fetchEntriesFromIndexCursor(cursor);
} else if (indexOperator instanceof OQueryOperatorMinor) {
final Object value = compiledFilter.getRootCondition().getRight();
OIndexCursor cursor = index.iterateEntriesMinor(getIndexKey(index.getDefinition(), value, context), false, ascOrder);
fetchEntriesFromIndexCursor(cursor);
} else if (indexOperator instanceof OQueryOperatorMinorEquals) {
final Object value = compiledFilter.getRootCondition().getRight();
OIndexCursor cursor = index.iterateEntriesMinor(getIndexKey(index.getDefinition(), value, context), true, ascOrder);
fetchEntriesFromIndexCursor(cursor);
} else if (indexOperator instanceof OQueryOperatorIn) {
final List<Object> origValues = (List<Object>) compiledFilter.getRootCondition().getRight();
final List<Object> values = new ArrayList<Object>(origValues.size());
for (Object val : origValues) {
if (index.getDefinition() instanceof OCompositeIndexDefinition) {
throw new OCommandExecutionException("Operator IN not supported yet.");
}
val = getIndexKey(index.getDefinition(), val, context);
values.add(val);
}
OIndexCursor cursor = index.iterateEntries(values, true);
fetchEntriesFromIndexCursor(cursor);
} else {
final Object right = compiledFilter.getRootCondition().getRight();
Object keyValue = getIndexKey(index.getDefinition(), right, context);
if (keyValue == null) {
return;
}
final Object res;
if (index.getDefinition().getParamCount() == 1) {
// CONVERT BEFORE SEARCH IF NEEDED
final OType type = index.getDefinition().getTypes()[0];
keyValue = OType.convert(keyValue, type.getDefaultJavaType());
res = index.get(keyValue);
} else {
final Object secondKey = getIndexKey(index.getDefinition(), right, context);
if (keyValue instanceof OCompositeKey && secondKey instanceof OCompositeKey && ((OCompositeKey) keyValue).getKeys().size() == index.getDefinition().getParamCount() && ((OCompositeKey) secondKey).getKeys().size() == index.getDefinition().getParamCount()) {
res = index.get(keyValue);
} else {
OIndexCursor cursor = index.iterateEntriesBetween(keyValue, true, secondKey, true, true);
fetchEntriesFromIndexCursor(cursor);
return;
}
}
if (res != null) {
if (res instanceof Collection<?>) {
// MULTI VALUES INDEX
for (final OIdentifiable r : (Collection<OIdentifiable>) res) {
final ODocument record = createIndexEntryAsDocument(keyValue, r.getIdentity());
applyGroupBy(record, context);
if (!handleResult(record, context)) // LIMIT REACHED
{
break;
}
}
} else {
// SINGLE VALUE INDEX
final ODocument record = createIndexEntryAsDocument(keyValue, ((OIdentifiable) res).getIdentity());
applyGroupBy(record, context);
handleResult(record, context);
}
}
}
} else {
if (isIndexSizeQuery()) {
getProjectionGroup(null, context).applyValue(projections.keySet().iterator().next(), index.getSize());
return;
}
if (isIndexKeySizeQuery()) {
getProjectionGroup(null, context).applyValue(projections.keySet().iterator().next(), index.getKeySize());
return;
}
final OIndexInternal<?> indexInternal = index.getInternal();
if (indexInternal instanceof OSharedResource) {
((OSharedResource) indexInternal).acquireExclusiveLock();
}
try {
// ADD ALL THE ITEMS AS RESULT
if (ascOrder) {
final OIndexCursor cursor = index.cursor();
fetchEntriesFromIndexCursor(cursor);
} else {
final OIndexCursor cursor = index.descCursor();
fetchEntriesFromIndexCursor(cursor);
}
} finally {
if (indexInternal instanceof OSharedResource) {
((OSharedResource) indexInternal).releaseExclusiveLock();
}
}
}
}
Aggregations