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;
}
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;
}
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;
}
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);
}
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);
}
}
Aggregations