Search in sources :

Example 1 with OCommandContext

use of com.orientechnologies.orient.core.command.OCommandContext in project orientdb by orientechnologies.

the class ODocumentHelper method getFieldValue.

@SuppressWarnings("unchecked")
public static <RET> RET getFieldValue(Object value, final String iFieldName, final OCommandContext iContext) {
    if (value == null)
        return null;
    final int fieldNameLength = iFieldName.length();
    if (fieldNameLength == 0)
        return (RET) value;
    OIdentifiable currentRecord = value instanceof OIdentifiable ? (OIdentifiable) value : null;
    int beginPos = iFieldName.charAt(0) == '.' ? 1 : 0;
    int nextSeparatorPos = iFieldName.charAt(0) == '.' ? 1 : 0;
    boolean firstInChain = true;
    do {
        char nextSeparator = ' ';
        for (; nextSeparatorPos < fieldNameLength; ++nextSeparatorPos) {
            nextSeparator = iFieldName.charAt(nextSeparatorPos);
            if (nextSeparator == '.' || nextSeparator == '[')
                break;
        }
        final String fieldName;
        if (nextSeparatorPos < fieldNameLength)
            fieldName = iFieldName.substring(beginPos, nextSeparatorPos);
        else {
            nextSeparator = ' ';
            if (beginPos > 0)
                fieldName = iFieldName.substring(beginPos);
            else
                fieldName = iFieldName;
        }
        if (nextSeparator == '[') {
            if (fieldName != null && fieldName.length() > 0) {
                if (currentRecord != null)
                    value = getIdentifiableValue(currentRecord, fieldName);
                else if (value instanceof Map<?, ?>)
                    value = getMapEntry((Map<String, ?>) value, fieldName);
                else if (OMultiValue.isMultiValue(value)) {
                    final HashSet<Object> temp = new LinkedHashSet<Object>();
                    for (Object o : OMultiValue.getMultiValueIterable(value, false)) {
                        if (o instanceof OIdentifiable) {
                            Object r = getFieldValue(o, iFieldName);
                            if (r != null)
                                OMultiValue.add(temp, r);
                        }
                    }
                    value = temp;
                }
            }
            if (value == null)
                return null;
            else if (value instanceof OIdentifiable)
                currentRecord = (OIdentifiable) value;
            // final int end = iFieldName.indexOf(']', nextSeparatorPos);
            final int end = findClosingBracketPosition(iFieldName, nextSeparatorPos);
            if (end == -1)
                throw new IllegalArgumentException("Missed closed ']'");
            String indexPart = iFieldName.substring(nextSeparatorPos + 1, end);
            if (indexPart.length() == 0)
                return null;
            nextSeparatorPos = end;
            if (value instanceof OCommandContext)
                value = ((OCommandContext) value).getVariables();
            if (value instanceof OIdentifiable) {
                final ORecord record = currentRecord != null && currentRecord instanceof OIdentifiable ? ((OIdentifiable) currentRecord).getRecord() : null;
                final Object index = getIndexPart(iContext, indexPart);
                final String indexAsString = index != null ? index.toString() : null;
                final List<String> indexParts = OStringSerializerHelper.smartSplit(indexAsString, ',', OStringSerializerHelper.DEFAULT_IGNORE_CHARS);
                final List<String> indexRanges = OStringSerializerHelper.smartSplit(indexAsString, '-', ' ');
                final List<String> indexCondition = OStringSerializerHelper.smartSplit(indexAsString, '=', ' ');
                if (indexParts.size() == 1 && indexCondition.size() == 1 && indexRanges.size() == 1)
                    // SINGLE VALUE
                    value = ((ODocument) record).field(indexAsString);
                else if (indexParts.size() > 1) {
                    // MULTI VALUE
                    final Object[] values = new Object[indexParts.size()];
                    for (int i = 0; i < indexParts.size(); ++i) {
                        values[i] = ((ODocument) record).field(OIOUtils.getStringContent(indexParts.get(i)));
                    }
                    value = values;
                } else if (indexRanges.size() > 1) {
                    // MULTI VALUES RANGE
                    String from = indexRanges.get(0);
                    String to = indexRanges.get(1);
                    final ODocument doc = (ODocument) record;
                    final String[] fieldNames = doc.fieldNames();
                    final int rangeFrom = from != null && !from.isEmpty() ? Integer.parseInt(from) : 0;
                    final int rangeTo = to != null && !to.isEmpty() ? Math.min(Integer.parseInt(to), fieldNames.length - 1) : fieldNames.length - 1;
                    final Object[] values = new Object[rangeTo - rangeFrom + 1];
                    for (int i = rangeFrom; i <= rangeTo; ++i) values[i - rangeFrom] = doc.field(fieldNames[i]);
                    value = values;
                } else if (!indexCondition.isEmpty()) {
                    // CONDITION
                    final String conditionFieldName = indexCondition.get(0);
                    Object conditionFieldValue = ORecordSerializerStringAbstract.getTypeValue(indexCondition.get(1));
                    if (conditionFieldValue instanceof String)
                        conditionFieldValue = OIOUtils.getStringContent(conditionFieldValue);
                    final Object fieldValue = getFieldValue(currentRecord, conditionFieldName);
                    if (conditionFieldValue != null && fieldValue != null)
                        conditionFieldValue = OType.convert(conditionFieldValue, fieldValue.getClass());
                    if (fieldValue == null && !conditionFieldValue.equals("null") || fieldValue != null && !fieldValue.equals(conditionFieldValue))
                        value = null;
                }
            } else if (value instanceof Map<?, ?>) {
                final Object index = getIndexPart(iContext, indexPart);
                final String indexAsString = index != null ? index.toString() : null;
                final List<String> indexParts = OStringSerializerHelper.smartSplit(indexAsString, ',', OStringSerializerHelper.DEFAULT_IGNORE_CHARS);
                final List<String> indexRanges = OStringSerializerHelper.smartSplit(indexAsString, '-', ' ');
                final List<String> indexCondition = OStringSerializerHelper.smartSplit(indexAsString, '=', ' ');
                final Map<String, ?> map = (Map<String, ?>) value;
                if (indexParts.size() == 1 && indexCondition.size() == 1 && indexRanges.size() == 1)
                    // SINGLE VALUE
                    value = map.get(index);
                else if (indexParts.size() > 1) {
                    // MULTI VALUE
                    final Object[] values = new Object[indexParts.size()];
                    for (int i = 0; i < indexParts.size(); ++i) {
                        values[i] = map.get(OIOUtils.getStringContent(indexParts.get(i)));
                    }
                    value = values;
                } else if (indexRanges.size() > 1) {
                    // MULTI VALUES RANGE
                    String from = indexRanges.get(0);
                    String to = indexRanges.get(1);
                    final List<String> fieldNames = new ArrayList<String>(map.keySet());
                    final int rangeFrom = from != null && !from.isEmpty() ? Integer.parseInt(from) : 0;
                    final int rangeTo = to != null && !to.isEmpty() ? Math.min(Integer.parseInt(to), fieldNames.size() - 1) : fieldNames.size() - 1;
                    final Object[] values = new Object[rangeTo - rangeFrom + 1];
                    for (int i = rangeFrom; i <= rangeTo; ++i) values[i - rangeFrom] = map.get(fieldNames.get(i));
                    value = values;
                } else if (!indexCondition.isEmpty()) {
                    // CONDITION
                    final String conditionFieldName = indexCondition.get(0);
                    Object conditionFieldValue = ORecordSerializerStringAbstract.getTypeValue(indexCondition.get(1));
                    if (conditionFieldValue instanceof String)
                        conditionFieldValue = OIOUtils.getStringContent(conditionFieldValue);
                    final Object fieldValue = map.get(conditionFieldName);
                    if (conditionFieldValue != null && fieldValue != null)
                        conditionFieldValue = OType.convert(conditionFieldValue, fieldValue.getClass());
                    if (fieldValue == null && !conditionFieldValue.equals("null") || fieldValue != null && !fieldValue.equals(conditionFieldValue))
                        value = null;
                }
            } else if (OMultiValue.isMultiValue(value)) {
                // MULTI VALUE
                final Object index = getIndexPart(iContext, indexPart);
                final String indexAsString = index != null ? index.toString() : null;
                final List<String> indexParts = OStringSerializerHelper.smartSplit(indexAsString, ',');
                final List<String> indexRanges = OStringSerializerHelper.smartSplit(indexAsString, '-');
                final List<String> indexCondition = OStringSerializerHelper.smartSplit(indexAsString, '=', ' ');
                if (isFieldName(indexAsString)) {
                    // SINGLE VALUE
                    if (value instanceof Map<?, ?>)
                        value = getMapEntry((Map<String, ?>) value, index);
                    else if (Character.isDigit(indexAsString.charAt(0)))
                        value = OMultiValue.getValue(value, Integer.parseInt(indexAsString));
                    else
                        // FILTER BY FIELD
                        value = getFieldValue(value, indexAsString, iContext);
                } else if (isListOfNumbers(indexParts)) {
                    // MULTI VALUES
                    final Object[] values = new Object[indexParts.size()];
                    for (int i = 0; i < indexParts.size(); ++i) values[i] = OMultiValue.getValue(value, Integer.parseInt(indexParts.get(i)));
                    if (indexParts.size() > 1) {
                        value = values;
                    } else {
                        value = values[0];
                    }
                } else if (isListOfNumbers(indexRanges)) {
                    // MULTI VALUES RANGE
                    String from = indexRanges.get(0);
                    String to = indexRanges.get(1);
                    final int rangeFrom = from != null && !from.isEmpty() ? Integer.parseInt(from) : 0;
                    final int rangeTo = to != null && !to.isEmpty() ? Math.min(Integer.parseInt(to), OMultiValue.getSize(value) - 1) : OMultiValue.getSize(value) - 1;
                    int arraySize = rangeTo - rangeFrom + 1;
                    if (arraySize < 0) {
                        arraySize = 0;
                    }
                    final Object[] values = new Object[arraySize];
                    for (int i = rangeFrom; i <= rangeTo; ++i) values[i - rangeFrom] = OMultiValue.getValue(value, i);
                    value = values;
                } else {
                    // CONDITION
                    OSQLPredicate pred = new OSQLPredicate(indexAsString);
                    final HashSet<Object> values = new LinkedHashSet<Object>();
                    for (Object v : OMultiValue.getMultiValueIterable(value)) {
                        if (v instanceof OIdentifiable) {
                            Object result = pred.evaluate((OIdentifiable) v, (ODocument) ((OIdentifiable) v).getRecord(), iContext);
                            if (Boolean.TRUE.equals(result)) {
                                values.add(v);
                            }
                        }
                    }
                    if (values.isEmpty())
                        // RETURNS NULL
                        value = values;
                    else if (values.size() == 1)
                        // RETURNS THE SINGLE ODOCUMENT
                        value = values.iterator().next();
                    else
                        // RETURNS THE FILTERED COLLECTION
                        value = values;
                }
            }
        } else {
            if (fieldName.length() == 0) {
                // NO FIELD NAME: THIS IS THE CASE OF NOT USEFUL . AFTER A ] OR .
                beginPos = ++nextSeparatorPos;
                continue;
            }
            if (fieldName.startsWith("$"))
                value = iContext.getVariable(fieldName);
            else if (fieldName.contains("(")) {
                boolean executedMethod = false;
                if (!firstInChain && fieldName.endsWith("()")) {
                    OSQLMethod method = OSQLEngine.getInstance().getMethod(fieldName.substring(0, fieldName.length() - 2));
                    if (method != null) {
                        value = method.execute(value, currentRecord, iContext, value, new Object[] {});
                        executedMethod = true;
                    }
                }
                if (!executedMethod) {
                    value = evaluateFunction(value, fieldName, iContext);
                }
            } else {
                final List<String> indexCondition = OStringSerializerHelper.smartSplit(fieldName, '=', ' ');
                if (indexCondition.size() == 2) {
                    final String conditionFieldName = indexCondition.get(0);
                    Object conditionFieldValue = ORecordSerializerStringAbstract.getTypeValue(indexCondition.get(1));
                    if (conditionFieldValue instanceof String)
                        conditionFieldValue = OIOUtils.getStringContent(conditionFieldValue);
                    value = filterItem(conditionFieldName, conditionFieldValue, value);
                } else if (currentRecord != null) {
                    // GET THE LINKED OBJECT IF ANY
                    value = getIdentifiableValue(currentRecord, fieldName);
                    if (value != null && value instanceof ORecord && ((ORecord) value).getInternalStatus() == STATUS.NOT_LOADED)
                        // RELOAD IT
                        ((ORecord) value).reload();
                } else if (value instanceof Map<?, ?>)
                    value = getMapEntry((Map<String, ?>) value, fieldName);
                else if (OMultiValue.isMultiValue(value)) {
                    final Set<Object> values = new LinkedHashSet<Object>();
                    for (Object v : OMultiValue.getMultiValueIterable(value, false)) {
                        final Object item;
                        if (v instanceof OIdentifiable)
                            item = getIdentifiableValue((OIdentifiable) v, fieldName);
                        else if (v instanceof Map)
                            item = ((Map<?, ?>) v).get(fieldName);
                        else
                            item = null;
                        if (item != null)
                            if (item instanceof Collection<?>)
                                values.addAll((Collection<? extends Object>) item);
                            else
                                values.add(item);
                    }
                    if (values.isEmpty())
                        value = null;
                    else
                        value = values;
                } else
                    return null;
            }
        }
        if (value instanceof OIdentifiable)
            currentRecord = (OIdentifiable) value;
        else
            currentRecord = null;
        beginPos = ++nextSeparatorPos;
        firstInChain = false;
    } while (nextSeparatorPos < fieldNameLength && value != null);
    return (RET) value;
}
Also used : OCommandContext(com.orientechnologies.orient.core.command.OCommandContext) OSQLPredicate(com.orientechnologies.orient.core.sql.filter.OSQLPredicate) ORecord(com.orientechnologies.orient.core.record.ORecord) OSQLMethod(com.orientechnologies.orient.core.sql.method.OSQLMethod)

Example 2 with OCommandContext

use of com.orientechnologies.orient.core.command.OCommandContext 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.interrupted();
            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) {
                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;
}
Also used : OCommandContext(com.orientechnologies.orient.core.command.OCommandContext) ODatabaseDocumentInternal(com.orientechnologies.orient.core.db.ODatabaseDocumentInternal) OException(com.orientechnologies.common.exception.OException) OQueryParsingException(com.orientechnologies.orient.core.exception.OQueryParsingException) OCommandExecutionException(com.orientechnologies.orient.core.exception.OCommandExecutionException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Future(java.util.concurrent.Future) OCommandExecutionException(com.orientechnologies.orient.core.exception.OCommandExecutionException) OCommandExecutionException(com.orientechnologies.orient.core.exception.OCommandExecutionException) ExecutionException(java.util.concurrent.ExecutionException)

Example 3 with OCommandContext

use of com.orientechnologies.orient.core.command.OCommandContext in project orientdb by orientechnologies.

the class OETLProcessor method createDefaultContext.

protected static OCommandContext createDefaultContext() {
    final OCommandContext context = new OBasicCommandContext();
    context.setVariable("dumpEveryMs", 1000);
    return context;
}
Also used : OBasicCommandContext(com.orientechnologies.orient.core.command.OBasicCommandContext) OCommandContext(com.orientechnologies.orient.core.command.OCommandContext)

Example 4 with OCommandContext

use of com.orientechnologies.orient.core.command.OCommandContext in project orientdb by orientechnologies.

the class DocumentTest method testEvalInContext.

@Test
public void testEvalInContext() {
    ODocument doc = new ODocument();
    doc.field("amount", 300);
    OCommandContext context = new OBasicCommandContext().setVariable("vat", 20);
    Number amountPlusVat = (Number) doc.eval("amount * (100 + $vat) / 100", context);
    Assert.assertEquals(amountPlusVat.longValue(), 360l);
}
Also used : OBasicCommandContext(com.orientechnologies.orient.core.command.OBasicCommandContext) OCommandContext(com.orientechnologies.orient.core.command.OCommandContext) ODocument(com.orientechnologies.orient.core.record.impl.ODocument) Test(org.testng.annotations.Test)

Example 5 with OCommandContext

use of com.orientechnologies.orient.core.command.OCommandContext in project orientdb by orientechnologies.

the class OLuceneFullTextIndexEngine method getInTx.

@Override
public Object getInTx(Object key, OLuceneTxChanges changes) {
    try {
        Query q = queryBuilder.query(index, key, queryAnalyzer());
        OCommandContext context = null;
        if (key instanceof OLuceneCompositeKey) {
            context = ((OLuceneCompositeKey) key).getContext();
        }
        return getResults(q, context, key, changes);
    } catch (ParseException e) {
        throw OException.wrapException(new OIndexEngineException("Error parsing lucene query"), e);
    }
}
Also used : OLuceneCompositeKey(com.orientechnologies.lucene.collections.OLuceneCompositeKey) Query(org.apache.lucene.search.Query) OCommandContext(com.orientechnologies.orient.core.command.OCommandContext) ParseException(com.orientechnologies.orient.core.sql.parser.ParseException) OIndexEngineException(com.orientechnologies.orient.core.index.OIndexEngineException)

Aggregations

OCommandContext (com.orientechnologies.orient.core.command.OCommandContext)9 ODocument (com.orientechnologies.orient.core.record.impl.ODocument)4 OIdentifiable (com.orientechnologies.orient.core.db.record.OIdentifiable)3 Test (org.testng.annotations.Test)3 OBasicCommandContext (com.orientechnologies.orient.core.command.OBasicCommandContext)2 OCommandExecutionException (com.orientechnologies.orient.core.exception.OCommandExecutionException)2 OQueryParsingException (com.orientechnologies.orient.core.exception.OQueryParsingException)2 IOException (java.io.IOException)2 OException (com.orientechnologies.common.exception.OException)1 OLuceneCompositeKey (com.orientechnologies.lucene.collections.OLuceneCompositeKey)1 OCommandPredicate (com.orientechnologies.orient.core.command.OCommandPredicate)1 OTraverse (com.orientechnologies.orient.core.command.traverse.OTraverse)1 ODatabaseDocumentInternal (com.orientechnologies.orient.core.db.ODatabaseDocumentInternal)1 OConfigurationException (com.orientechnologies.orient.core.exception.OConfigurationException)1 ORecordId (com.orientechnologies.orient.core.id.ORecordId)1 OIndexEngineException (com.orientechnologies.orient.core.index.OIndexEngineException)1 OClass (com.orientechnologies.orient.core.metadata.schema.OClass)1 ORecord (com.orientechnologies.orient.core.record.ORecord)1 OSQLPredicate (com.orientechnologies.orient.core.sql.filter.OSQLPredicate)1 OSQLFunctionAbstract (com.orientechnologies.orient.core.sql.functions.OSQLFunctionAbstract)1