
oracle.kv.impl.api.ops.TableQueryHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oracle-nosql-server Show documentation
Show all versions of oracle-nosql-server Show documentation
NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.
The newest version!
/*-
* Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle NoSQL
* Database made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle NoSQL Database for a copy of the license and
* additional information.
*/
package oracle.kv.impl.api.ops;
import java.util.ArrayList;
import java.util.List;
import oracle.kv.FaultException;
import oracle.kv.impl.api.ops.InternalOperation.OpCode;
import oracle.kv.impl.api.table.FieldValueImpl;
import oracle.kv.impl.api.table.TableMetadata;
import oracle.kv.impl.api.table.TableMetadataHelper;
import oracle.kv.impl.api.table.TupleValue;
import oracle.kv.impl.fault.RNUnavailableException;
import oracle.kv.impl.fault.WrappedClientException;
import oracle.kv.impl.metadata.Metadata.MetadataType;
import oracle.kv.impl.query.QueryException;
import oracle.kv.impl.query.QueryRuntimeException;
import oracle.kv.impl.query.QueryStateException;
import oracle.kv.impl.query.runtime.PlanIter;
import oracle.kv.impl.query.runtime.ResumeInfo;
import oracle.kv.impl.query.runtime.RuntimeControlBlock;
import oracle.kv.impl.query.runtime.server.ServerIterFactoryImpl;
import oracle.kv.impl.security.KVStorePrivilege;
import oracle.kv.impl.security.SystemPrivilege;
import oracle.kv.impl.topo.PartitionId;
import oracle.kv.query.ExecuteOptions;
import com.sleepycat.je.Transaction;
import oracle.kv.impl.api.table.TableVersionException;
/**
* Server handler for {@link TableQuery}.
*/
class TableQueryHandler extends InternalOperationHandler {
TableQueryHandler(OperationHandler handler, OpCode opCode) {
super(handler, opCode, TableQuery.class);
}
@Override
List extends KVStorePrivilege> getRequiredPrivileges(TableQuery op) {
/*
* Checks the basic privilege for authentication here, and leave the
* keyspace checking and the table access checking in
* {@code verifyTableAccess()}.
*/
return SystemPrivilege.usrviewPrivList;
}
@Override
Result execute(TableQuery op,
Transaction txn,
PartitionId partitionId) {
final int batchSize = op.getBatchSize();
final List results =
new ArrayList(batchSize);
TableMetadataHelper mdHelper = getMetadataHelper();
ExecuteOptions options = new ExecuteOptions();
options.setResultsBatchSize(batchSize);
options.setTraceLevel(op.getTraceLevel());
options.setMathContext(op.getMathContext());
options.setMaxReadKB(op.getMaxReadKB());
RuntimeControlBlock rcb = new RuntimeControlBlock(
null, /* KVStoreImpl not needed and not available */
getLogger(),
mdHelper,
null, /* partitions */
null, /* shards */
options,
op,
new ServerIterFactoryImpl(txn, partitionId, operationHandler),
op.getQueryPlan(),
op.getNumIterators(),
op.getNumRegisters(),
op.getExternalVars());
ResumeInfo ri = op.getResumeInfo();
ri.setRCB(rcb);
if (rcb.getTraceLevel() >= 1) {
rcb.trace("Executing query on partition " + partitionId);
rcb.trace(op.getQueryPlan().display());
}
if (rcb.getTraceLevel() >= 2) {
rcb.trace("Resume Info:\n" + ri);
}
executeQueryPlan(op, rcb, results, partitionId);
/*
* Resume key is both input and output parameter for RCB. If set on
* output there are more keys to be found in this iteration.
*/
ri.setNumResultsComputed(results.size());
byte[] newPrimaryResumeKey = ri.getPrimResumeKey();
byte[] newSecondaryResumeKey = ri.getSecResumeKey();
boolean more = (rcb.getReachedLimit() ||
(results.size() == batchSize &&
(newPrimaryResumeKey != null ||
newSecondaryResumeKey != null)));
if (rcb.getTraceLevel() >= 1) {
rcb.trace("Produced a batch of " + results.size() +
" results on partition " + partitionId +
" number of KB read = " + rcb.getReadKB() +
" more results = " + more);
if (rcb.getTraceLevel() >= 2) {
rcb.trace(ri.toString());
}
}
return new Result.QueryResult(getOpCode(),
rcb.getReadKB(),
rcb.getWriteKB(),
results,
op.getResultDef(),
op.mayReturnNULL(),
more,
ri,
rcb.getReachedLimit());
}
/**
* Returns a TableMetadataHelper instance available on this node.
*/
private TableMetadataHelper getMetadataHelper() {
final TableMetadata md =
(TableMetadata) getRepNode().getMetadata(MetadataType.TABLE);
if (md == null) {
final String msg = "Query execution unable to get metadata";
getLogger().warning(msg);
/*
* Wrap this exception into one that can be thrown to the client.
*/
new QueryStateException(msg).throwClientException();
}
return md;
}
private void executeQueryPlan(
TableQuery op,
RuntimeControlBlock rcb,
List results,
PartitionId pid) {
final int batchSize = op.getBatchSize();
final PlanIter queryPlan = op.getQueryPlan();
boolean noException = false;
try {
queryPlan.open(rcb);
while ((batchSize == 0 || results.size() < batchSize) &&
queryPlan.next(rcb)) {
FieldValueImpl res = rcb.getRegVal(queryPlan.getResultReg());
if (res.isTuple()) {
res = ((TupleValue)res).toRecord();
}
if (rcb.getTraceLevel() >= 2) {
rcb.trace("Produced result on " + pid + " :\n" +
res);
}
results.add(res);
}
noException = true;
/*
* The following multi-catch is so that some expected RuntimeExceptions
* can be propagated up to allow the request handler to deal with
* them as it does for other operations. Such exceptions, if not
* caught here, will be wrapped below in the catch of RuntimeException
* and will be logged (with stack trace) and re-thrown. As new
* exceptions of this nature are found, please add to this catch.
*
* FaultExceptions are likely ResourceLimitExceptions and should
* be passed up to the user as-is.
*
* A RNUE is likely due to the RN being in the middle of updating
* state associated with tables and indexes.
*
* TableVersionException is due to the client and store table
* metadata being out of sync with each other.
*/
} catch (FaultException |
RNUnavailableException |
TableVersionException re) {
throw re;
} catch (QueryException qe) {
/*
* For debugging and tracing this can temporarily use level INFO
*/
getLogger().fine("Query execution failed: " + qe);
/*
* Turn this into a wrapped IllegalArgumentException so that it can
* be passed to the client.
*/
throw qe.getWrappedIllegalArgument();
} catch (QueryStateException qse) {
/*
* This exception indicates a bug or problem in the engine. Log
* it. It will be thrown through to the client side.
*/
getLogger().warning(qse.toString());
/*
* Wrap this exception into one that can be thrown to the client.
*/
qse.throwClientException();
} catch (IllegalArgumentException e) {
throw new WrappedClientException(e);
} catch (RuntimeException re) {
/*
* RuntimeException should not be caught here. REs should be
* propagated up to the request handler as many are explicitly
* handled there. The issue is that the query code can throw REs
* which it should catch and turn into something specific (such as
* an IAE). Until that time this needs to remain to avoid the
* RN restarting due to some minor query issue.
*/
throw new QueryRuntimeException(re);
} finally {
try {
queryPlan.close(rcb);
} catch (RuntimeException re) {
if (noException) {
throw new QueryRuntimeException(re);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy