Search in sources :

Example 66 with SqlFieldsQuery

use of org.apache.ignite.cache.query.SqlFieldsQuery in project ignite by apache.

the class IgniteH2Indexing method querySqlFields.

/**
 * {@inheritDoc}
 */
@SuppressWarnings({ "StringEquality" })
@Override
public List<FieldsQueryCursor<List<?>>> querySqlFields(String schemaName, SqlFieldsQuery qry, @Nullable SqlClientContext cliCtx, boolean keepBinary, boolean failOnMultipleStmts, GridQueryCancel cancel) {
    try {
        List<FieldsQueryCursor<List<?>>> res = new ArrayList<>(1);
        SqlFieldsQuery remainingQry = qry;
        while (remainingQry != null) {
            Span qrySpan = ctx.tracing().create(SQL_QRY, MTC.span()).addTag(SQL_SCHEMA, () -> schemaName);
            try (TraceSurroundings ignored = MTC.supportContinual(qrySpan)) {
                // Parse.
                QueryParserResult parseRes = parser.parse(schemaName, remainingQry, !failOnMultipleStmts);
                qrySpan.addTag(SQL_QRY_TEXT, () -> parseRes.queryDescriptor().sql());
                remainingQry = parseRes.remainingQuery();
                // Get next command.
                QueryDescriptor newQryDesc = parseRes.queryDescriptor();
                QueryParameters newQryParams = parseRes.queryParameters();
                // since they pass parameters differently.
                if (!newQryDesc.batched()) {
                    int qryParamsCnt = F.isEmpty(newQryParams.arguments()) ? 0 : newQryParams.arguments().length;
                    if (qryParamsCnt < parseRes.parametersCount())
                        throw new IgniteSQLException("Invalid number of query parameters [expected=" + parseRes.parametersCount() + ", actual=" + qryParamsCnt + ']');
                }
                // Check if cluster state is valid.
                checkClusterState(parseRes);
                // Execute.
                if (parseRes.isCommand()) {
                    QueryParserResultCommand cmd = parseRes.command();
                    assert cmd != null;
                    FieldsQueryCursor<List<?>> cmdRes = executeCommand(newQryDesc, newQryParams, cliCtx, cmd);
                    res.add(cmdRes);
                } else if (parseRes.isDml()) {
                    QueryParserResultDml dml = parseRes.dml();
                    assert dml != null;
                    List<? extends FieldsQueryCursor<List<?>>> dmlRes = executeDml(newQryDesc, newQryParams, dml, cancel);
                    res.addAll(dmlRes);
                } else {
                    assert parseRes.isSelect();
                    QueryParserResultSelect select = parseRes.select();
                    assert select != null;
                    List<? extends FieldsQueryCursor<List<?>>> qryRes = executeSelect(newQryDesc, newQryParams, select, keepBinary, cancel);
                    res.addAll(qryRes);
                }
            } catch (Throwable th) {
                qrySpan.addTag(ERROR, th::getMessage).end();
                throw th;
            }
        }
        return res;
    } catch (RuntimeException | Error e) {
        GridNearTxLocal tx = ctx.cache().context().tm().tx();
        if (tx != null && tx.mvccSnapshot() != null && (!(e instanceof IgniteSQLException) || /* Parsing errors should not rollback Tx. */
        ((IgniteSQLException) e).sqlState() != SqlStateCode.PARSING_EXCEPTION))
            tx.setRollbackOnly();
        throw e;
    }
}
Also used : FieldsQueryCursor(org.apache.ignite.cache.query.FieldsQueryCursor) ArrayList(java.util.ArrayList) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) Span(org.apache.ignite.internal.processors.tracing.Span) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) TraceSurroundings(org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) Collections.singletonList(java.util.Collections.singletonList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 67 with SqlFieldsQuery

use of org.apache.ignite.cache.query.SqlFieldsQuery in project ignite by apache.

the class IgniteH2Indexing method executeUpdateNonTransactional.

/**
 * Execute update in non-transactional mode.
 *
 * @param qryId Query id.
 * @param qryDesc Query descriptor.
 * @param qryParams Query parameters.
 * @param dml Plan.
 * @param loc Local flag.
 * @param filters Filters.
 * @param cancel Cancel hook.
 * @return Update result.
 * @throws IgniteCheckedException If failed.
 */
private UpdateResult executeUpdateNonTransactional(long qryId, QueryDescriptor qryDesc, QueryParameters qryParams, QueryParserResultDml dml, boolean loc, IndexingQueryFilter filters, GridQueryCancel cancel) throws IgniteCheckedException {
    UpdatePlan plan = dml.plan();
    UpdateResult fastUpdateRes = plan.processFast(qryParams.arguments());
    if (fastUpdateRes != null)
        return fastUpdateRes;
    DmlDistributedPlanInfo distributedPlan = loc ? null : plan.distributedPlan();
    if (distributedPlan != null) {
        if (cancel == null)
            cancel = new GridQueryCancel();
        UpdateResult result = rdcQryExec.update(qryDesc.schemaName(), distributedPlan.getCacheIds(), qryDesc.sql(), qryParams.arguments(), qryDesc.enforceJoinOrder(), qryParams.pageSize(), qryParams.timeout(), qryParams.partitions(), distributedPlan.isReplicatedOnly(), cancel);
        // Null is returned in case not all nodes support distributed DML.
        if (result != null)
            return result;
    }
    final GridQueryCancel selectCancel = (cancel != null) ? new GridQueryCancel() : null;
    if (cancel != null)
        cancel.add(selectCancel::cancel);
    SqlFieldsQuery selectFieldsQry = new SqlFieldsQuery(plan.selectQuery(), qryDesc.collocated()).setArgs(qryParams.arguments()).setDistributedJoins(qryDesc.distributedJoins()).setEnforceJoinOrder(qryDesc.enforceJoinOrder()).setLocal(qryDesc.local()).setPageSize(qryParams.pageSize()).setTimeout(qryParams.timeout(), TimeUnit.MILLISECONDS).setLazy(qryParams.lazy() && plan.canSelectBeLazy());
    Iterable<List<?>> cur;
    // sub-query and not some dummy stuff like "select 1, 2, 3;"
    if (!loc && !plan.isLocalSubquery()) {
        assert !F.isEmpty(plan.selectQuery());
        cur = executeSelectForDml(qryId, qryDesc.schemaName(), selectFieldsQry, null, selectCancel, qryParams.timeout());
    } else if (plan.hasRows())
        cur = plan.createRows(qryParams.arguments());
    else {
        selectFieldsQry.setLocal(true);
        QueryParserResult selectParseRes = parser.parse(qryDesc.schemaName(), selectFieldsQry, false);
        final GridQueryFieldsResult res = executeSelectLocal(qryId, selectParseRes.queryDescriptor(), selectParseRes.queryParameters(), selectParseRes.select(), filters, null, selectCancel, false, qryParams.timeout());
        cur = new QueryCursorImpl<>(new Iterable<List<?>>() {

            @Override
            public Iterator<List<?>> iterator() {
                try {
                    return new GridQueryCacheObjectsIterator(res.iterator(), objectContext(), true);
                } catch (IgniteCheckedException e) {
                    throw new IgniteException(e);
                }
            }
        }, cancel, true, qryParams.lazy());
    }
    int pageSize = qryParams.updateBatchSize();
    // TODO: IGNITE-11176 - Need to support cancellation
    try {
        return DmlUtils.processSelectResult(plan, cur, pageSize);
    } finally {
        if (cur instanceof AutoCloseable)
            U.closeQuiet((AutoCloseable) cur);
    }
}
Also used : DmlDistributedPlanInfo(org.apache.ignite.internal.processors.query.h2.dml.DmlDistributedPlanInfo) QueryCursorImpl(org.apache.ignite.internal.processors.cache.QueryCursorImpl) GridQueryCacheObjectsIterator(org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) GridQueryFieldsResult(org.apache.ignite.internal.processors.query.GridQueryFieldsResult) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteException(org.apache.ignite.IgniteException) GridQueryCancel(org.apache.ignite.internal.processors.query.GridQueryCancel) GridQueryCacheObjectsIterator(org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator) UpdateSourceIterator(org.apache.ignite.internal.processors.query.UpdateSourceIterator) GridCloseableIterator(org.apache.ignite.internal.util.lang.GridCloseableIterator) GridEmptyCloseableIterator(org.apache.ignite.internal.util.GridEmptyCloseableIterator) DmlUpdateSingleEntryIterator(org.apache.ignite.internal.processors.query.h2.dml.DmlUpdateSingleEntryIterator) DmlUpdateResultsIterator(org.apache.ignite.internal.processors.query.h2.dml.DmlUpdateResultsIterator) IgniteSingletonIterator(org.apache.ignite.internal.util.lang.IgniteSingletonIterator) Iterator(java.util.Iterator) Collections.singletonList(java.util.Collections.singletonList) ArrayList(java.util.ArrayList) List(java.util.List) UpdatePlan(org.apache.ignite.internal.processors.query.h2.dml.UpdatePlan)

Example 68 with SqlFieldsQuery

use of org.apache.ignite.cache.query.SqlFieldsQuery in project ignite by apache.

the class QueryParser method parseH2.

/**
 * Parse and split query if needed, cache either two-step query or statement.
 *
 * @param schemaName Schema name.
 * @param qry Query.
 * @param batched Batched flag.
 * @param remainingAllowed Whether multiple statements are allowed.
 * @return Parsing result.
 */
@SuppressWarnings("IfMayBeConditional")
private QueryParserResult parseH2(String schemaName, SqlFieldsQuery qry, boolean batched, boolean remainingAllowed) {
    try (H2PooledConnection c = connMgr.connection(schemaName)) {
        // For queries that are explicitly local, we rely on the flag specified in the query
        // because this parsing result will be cached and used for queries directly.
        // For other queries, we enforce join order at this stage to avoid premature optimizations
        // (and therefore longer parsing) as long as there'll be more parsing at split stage.
        boolean enforceJoinOrderOnParsing = (!qry.isLocal() || qry.isEnforceJoinOrder());
        QueryContext qctx = QueryContext.parseContext(idx.backupFilter(null, null), qry.isLocal());
        H2Utils.setupConnection(c, qctx, false, enforceJoinOrderOnParsing, false);
        PreparedStatement stmt = null;
        try {
            stmt = c.prepareStatementNoCache(qry.getSql());
            if (qry.isLocal() && GridSqlQueryParser.checkMultipleStatements(stmt))
                throw new IgniteSQLException("Multiple statements queries are not supported for local queries.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            GridSqlQueryParser.PreparedWithRemaining prep = GridSqlQueryParser.preparedWithRemaining(stmt);
            Prepared prepared = prep.prepared();
            if (GridSqlQueryParser.isExplainUpdate(prepared))
                throw new IgniteSQLException("Explains of update queries are not supported.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            // Get remaining query and check if it is allowed.
            SqlFieldsQuery remainingQry = null;
            if (!F.isEmpty(prep.remainingSql())) {
                checkRemainingAllowed(remainingAllowed);
                remainingQry = cloneFieldsQuery(qry).setSql(prep.remainingSql());
            }
            // Prepare new query.
            SqlFieldsQuery newQry = cloneFieldsQuery(qry).setSql(prepared.getSQL());
            final int paramsCnt = prepared.getParameters().size();
            Object[] argsOrig = qry.getArgs();
            Object[] args = null;
            Object[] remainingArgs = null;
            if (!batched && paramsCnt > 0) {
                if (argsOrig == null || argsOrig.length < paramsCnt)
                    // Not enough parameters, but we will handle this later on execution phase.
                    args = argsOrig;
                else {
                    args = Arrays.copyOfRange(argsOrig, 0, paramsCnt);
                    if (paramsCnt != argsOrig.length)
                        remainingArgs = Arrays.copyOfRange(argsOrig, paramsCnt, argsOrig.length);
                }
            } else
                remainingArgs = argsOrig;
            newQry.setArgs(args);
            QueryDescriptor newQryDesc = queryDescriptor(schemaName, newQry);
            if (remainingQry != null)
                remainingQry.setArgs(remainingArgs);
            final List<JdbcParameterMeta> paramsMeta;
            try {
                paramsMeta = H2Utils.parametersMeta(stmt.getParameterMetaData());
                assert prepared.getParameters().size() == paramsMeta.size();
            } catch (IgniteCheckedException | SQLException e) {
                throw new IgniteSQLException("Failed to get parameters metadata", IgniteQueryErrorCode.UNKNOWN, e);
            }
            // Do actual parsing.
            if (CommandProcessor.isCommand(prepared)) {
                GridSqlStatement cmdH2 = new GridSqlQueryParser(false, log).parse(prepared);
                QueryParserResultCommand cmd = new QueryParserResultCommand(null, cmdH2, false);
                return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, null, null, cmd);
            } else if (CommandProcessor.isCommandNoOp(prepared)) {
                QueryParserResultCommand cmd = new QueryParserResultCommand(null, null, true);
                return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, null, null, cmd);
            } else if (GridSqlQueryParser.isDml(prepared)) {
                QueryParserResultDml dml = prepareDmlStatement(newQryDesc, prepared);
                return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, null, dml, null);
            } else if (!prepared.isQuery()) {
                throw new IgniteSQLException("Unsupported statement: " + newQry.getSql(), IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            }
            // Parse SELECT.
            GridSqlQueryParser parser = new GridSqlQueryParser(false, log);
            GridSqlQuery selectStmt = (GridSqlQuery) parser.parse(prepared);
            List<Integer> cacheIds = parser.cacheIds();
            Integer mvccCacheId = mvccCacheIdForSelect(parser.objectsMap());
            // Calculate if query is in fact can be executed locally.
            boolean loc = qry.isLocal();
            if (!loc) {
                if (parser.isLocalQuery())
                    loc = true;
            }
            // If this is a local query, check if it must be split.
            boolean locSplit = false;
            if (loc) {
                GridCacheContext cctx = parser.getFirstPartitionedCache();
                if (cctx != null && cctx.config().getQueryParallelism() > 1)
                    locSplit = true;
            }
            // Split is required either if query is distributed, or when it is local, but executed
            // over segmented PARTITIONED case. In this case multiple map queries will be executed against local
            // node stripes in parallel and then merged through reduce process.
            boolean splitNeeded = !loc || locSplit;
            String forUpdateQryOutTx = null;
            String forUpdateQryTx = null;
            GridCacheTwoStepQuery forUpdateTwoStepQry = null;
            boolean forUpdate = GridSqlQueryParser.isForUpdateQuery(prepared);
            // column to be able to lock selected rows further.
            if (forUpdate) {
                // We have checked above that it's not an UNION query, so it's got to be SELECT.
                assert selectStmt instanceof GridSqlSelect;
                // Check FOR UPDATE invariants: only one table, MVCC is there.
                if (cacheIds.size() != 1)
                    throw new IgniteSQLException("SELECT FOR UPDATE is supported only for queries " + "that involve single transactional cache.");
                if (mvccCacheId == null)
                    throw new IgniteSQLException("SELECT FOR UPDATE query requires transactional cache " + "with MVCC enabled.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
                // We need a copy because we are going to modify AST a bit. We do not want to modify original select.
                GridSqlSelect selForUpdate = ((GridSqlSelect) selectStmt).copySelectForUpdate();
                // Clear forUpdate flag to run it as a plain query.
                selForUpdate.forUpdate(false);
                ((GridSqlSelect) selectStmt).forUpdate(false);
                // Remember sql string without FOR UPDATE clause.
                forUpdateQryOutTx = selForUpdate.getSQL();
                GridSqlAlias keyCol = keyColumn(selForUpdate);
                selForUpdate.addColumn(keyCol, true);
                // Remember sql string without FOR UPDATE clause and with _key column.
                forUpdateQryTx = selForUpdate.getSQL();
                // Prepare additional two-step query for FOR UPDATE case.
                if (splitNeeded) {
                    c.schema(newQry.getSchema());
                    forUpdateTwoStepQry = GridSqlQuerySplitter.split(c, selForUpdate, forUpdateQryTx, newQry.isCollocated(), newQry.isDistributedJoins(), newQry.isEnforceJoinOrder(), locSplit, idx, paramsCnt, log);
                }
            }
            GridCacheTwoStepQuery twoStepQry = null;
            if (splitNeeded) {
                GridSubqueryJoinOptimizer.pullOutSubQueries(selectStmt);
                c.schema(newQry.getSchema());
                twoStepQry = GridSqlQuerySplitter.split(c, selectStmt, newQry.getSql(), newQry.isCollocated(), newQry.isDistributedJoins(), newQry.isEnforceJoinOrder(), locSplit, idx, paramsCnt, log);
            }
            List<GridQueryFieldMetadata> meta = H2Utils.meta(stmt.getMetaData());
            QueryParserResultSelect select = new QueryParserResultSelect(selectStmt, twoStepQry, forUpdateTwoStepQry, meta, cacheIds, mvccCacheId, forUpdateQryOutTx, forUpdateQryTx);
            return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, select, null, null);
        } catch (IgniteCheckedException | SQLException e) {
            throw new IgniteSQLException("Failed to parse query. " + e.getMessage(), IgniteQueryErrorCode.PARSING, e);
        } finally {
            U.close(stmt, log);
        }
    }
}
Also used : GridSqlAlias(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias) SQLException(java.sql.SQLException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridSqlStatement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement) Prepared(org.h2.command.Prepared) GridCacheTwoStepQuery(org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery) GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) JdbcParameterMeta(org.apache.ignite.internal.processors.odbc.jdbc.JdbcParameterMeta) PreparedStatement(java.sql.PreparedStatement) QueryContext(org.apache.ignite.internal.processors.query.h2.opt.QueryContext) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) GridSqlQuery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery) GridSqlQueryParser(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException)

Example 69 with SqlFieldsQuery

use of org.apache.ignite.cache.query.SqlFieldsQuery in project ignite by apache.

the class IgniteSqlSkipReducerOnUpdateDmlSelfTest method testSpecificPartitionsUpdate.

/**
 * @throws Exception if failed.
 */
@Test
public void testSpecificPartitionsUpdate() throws Exception {
    fillCaches();
    Affinity aff = grid(NODE_CLIENT).affinity(CACHE_PERSON);
    int numParts = aff.partitions();
    int[] parts = new int[numParts / 2];
    for (int idx = 0; idx < numParts / 2; idx++) parts[idx] = idx * 2;
    IgniteCache<PersonKey, Person> cache = grid(NODE_CLIENT).cache(CACHE_PERSON);
    // UPDATE over even partitions
    cache.query(new SqlFieldsQueryEx("UPDATE Person SET position = 0", false).setSkipReducerOnUpdate(true).setPartitions(parts));
    List<List<?>> rows = cache.query(new SqlFieldsQuery("SELECT _key, position FROM Person")).getAll();
    for (List<?> row : rows) {
        PersonKey personKey = (PersonKey) row.get(0);
        int pos = ((Number) row.get(1)).intValue();
        int part = aff.partition(personKey);
        assertTrue((part % 2 == 0) ^ (pos != 0));
    }
}
Also used : SqlFieldsQueryEx(org.apache.ignite.internal.processors.cache.query.SqlFieldsQueryEx) Affinity(org.apache.ignite.cache.affinity.Affinity) ArrayList(java.util.ArrayList) List(java.util.List) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) AbstractIndexingCommonTest(org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest) Test(org.junit.Test)

Example 70 with SqlFieldsQuery

use of org.apache.ignite.cache.query.SqlFieldsQuery in project ignite by apache.

the class KillQueryErrorOnCancelTest method testCancelAfterIteratorObtainedLazy.

/**
 */
@Test
public void testCancelAfterIteratorObtainedLazy() throws Exception {
    IgniteEx node = grid(0);
    FieldsQueryCursor<List<?>> cur = node.context().query().querySqlFields(new SqlFieldsQuery("select * from \"default\".Integer ORDER BY _val").setLazy(true).setPageSize(1), false);
    Iterator<List<?>> it = cur.iterator();
    it.next();
    Long qryId = node.context().query().runningQueries(-1).iterator().next().id();
    GridTestUtils.assertThrows(log, () -> node.context().query().querySqlFields(createKillQuery(node.context().localNodeId(), qryId, false), false).getAll(), IgniteException.class, "Fake network error");
    List<GridRunningQueryInfo> runningQueries = (List<GridRunningQueryInfo>) node.context().query().runningQueries(-1);
    assertTrue("runningQueries=" + runningQueries, runningQueries.isEmpty());
    ensureMapQueriesHasFinished(grid(0));
    ensureMapQueriesHasFinished(grid(1));
}
Also used : IgniteEx(org.apache.ignite.internal.IgniteEx) List(java.util.List) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) GridAbstractTest(org.apache.ignite.testframework.junits.GridAbstractTest) GridCommonAbstractTest(org.apache.ignite.testframework.junits.common.GridCommonAbstractTest) Test(org.junit.Test)

Aggregations

SqlFieldsQuery (org.apache.ignite.cache.query.SqlFieldsQuery)679 Test (org.junit.Test)388 List (java.util.List)373 Ignite (org.apache.ignite.Ignite)170 ArrayList (java.util.ArrayList)136 IgniteCache (org.apache.ignite.IgniteCache)123 GridCommonAbstractTest (org.apache.ignite.testframework.junits.common.GridCommonAbstractTest)115 AbstractIndexingCommonTest (org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest)94 IgniteEx (org.apache.ignite.internal.IgniteEx)90 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)83 Transaction (org.apache.ignite.transactions.Transaction)80 CacheException (javax.cache.CacheException)67 Random (java.util.Random)55 CacheConfiguration (org.apache.ignite.configuration.CacheConfiguration)53 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)52 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)45 KeyCacheObject (org.apache.ignite.internal.processors.cache.KeyCacheObject)41 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)32 HashMap (java.util.HashMap)31 Cache (javax.cache.Cache)31