Search in sources :

Example 26 with Row

use of org.h2.result.Row in project ignite by apache.

the class GridH2TableSelfTest method testIndexFindFirstOrLast.

/**
     * @throws Exception If failed.
     */
public void testIndexFindFirstOrLast() throws Exception {
    Index index = tbl.getIndexes().get(2);
    assertTrue(index instanceof GridH2TreeIndex);
    assertTrue(index.canGetFirstOrLast());
    //find first on empty data
    Cursor cursor = index.findFirstOrLast(null, true);
    assertFalse(cursor.next());
    assertNull(cursor.get());
    //find last on empty data
    cursor = index.findFirstOrLast(null, false);
    assertFalse(cursor.next());
    assertNull(cursor.get());
    //fill with data
    int rows = 100;
    long t = System.currentTimeMillis();
    Random rnd = new Random();
    UUID min = null;
    UUID max = null;
    for (int i = 0; i < rows; i++) {
        UUID id = UUID.randomUUID();
        if (min == null || id.compareTo(min) < 0)
            min = id;
        if (max == null || id.compareTo(max) > 0)
            max = id;
        GridH2Row row = row(id, t++, id.toString(), rnd.nextInt(100));
        ((GridH2TreeIndex) index).put(row);
    }
    //find first
    cursor = index.findFirstOrLast(null, true);
    assertTrue(cursor.next());
    assertEquals(min, cursor.get().getValue(0).getObject());
    assertFalse(cursor.next());
    //find last
    cursor = index.findFirstOrLast(null, false);
    assertTrue(cursor.next());
    assertEquals(max, cursor.get().getValue(0).getObject());
    assertFalse(cursor.next());
}
Also used : Random(java.util.Random) Index(org.h2.index.Index) H2PkHashIndex(org.apache.ignite.internal.processors.query.h2.database.H2PkHashIndex) GridCursor(org.apache.ignite.internal.util.lang.GridCursor) Cursor(org.h2.index.Cursor) UUID(java.util.UUID)

Example 27 with Row

use of org.h2.result.Row in project ignite by apache.

the class UpdatePlanBuilder method planForUpdate.

/**
     * Prepare update plan for UPDATE or DELETE.
     *
     * @param stmt UPDATE or DELETE statement.
     * @param errKeysPos index to inject param for re-run keys at. Null if it's not a re-run plan.
     * @return Update plan.
     * @throws IgniteCheckedException if failed.
     */
private static UpdatePlan planForUpdate(GridSqlStatement stmt, @Nullable Integer errKeysPos) throws IgniteCheckedException {
    GridSqlElement target;
    FastUpdateArguments fastUpdate;
    UpdateMode mode;
    if (stmt instanceof GridSqlUpdate) {
        // Let's verify that user is not trying to mess with key's columns directly
        verifyUpdateColumns(stmt);
        GridSqlUpdate update = (GridSqlUpdate) stmt;
        target = update.target();
        fastUpdate = DmlAstUtils.getFastUpdateArgs(update);
        mode = UpdateMode.UPDATE;
    } else if (stmt instanceof GridSqlDelete) {
        GridSqlDelete del = (GridSqlDelete) stmt;
        target = del.from();
        fastUpdate = DmlAstUtils.getFastDeleteArgs(del);
        mode = UpdateMode.DELETE;
    } else
        throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION);
    GridSqlTable tbl = gridTableForElement(target);
    GridH2Table gridTbl = tbl.dataTable();
    GridH2RowDescriptor desc = gridTbl.rowDescriptor();
    if (desc == null)
        throw new IgniteSQLException("Row descriptor undefined for table '" + gridTbl.getName() + "'", IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR);
    if (fastUpdate != null)
        return UpdatePlan.forFastUpdate(mode, gridTbl, fastUpdate);
    else {
        GridSqlSelect sel;
        if (stmt instanceof GridSqlUpdate) {
            List<GridSqlColumn> updatedCols = ((GridSqlUpdate) stmt).cols();
            int valColIdx = -1;
            String[] colNames = new String[updatedCols.size()];
            int[] colTypes = new int[updatedCols.size()];
            for (int i = 0; i < updatedCols.size(); i++) {
                colNames[i] = updatedCols.get(i).columnName();
                colTypes[i] = updatedCols.get(i).resultType().type();
                Column column = updatedCols.get(i).column();
                if (desc.isValueColumn(column.getColumnId()))
                    valColIdx = i;
            }
            boolean hasNewVal = (valColIdx != -1);
            // Statement updates distinct properties if it does not have _val in updated columns list
            // or if its list of updated columns includes only _val, i.e. is single element.
            boolean hasProps = !hasNewVal || updatedCols.size() > 1;
            // Index of new _val in results of SELECT
            if (hasNewVal)
                valColIdx += 2;
            int newValColIdx = (hasNewVal ? valColIdx : 1);
            KeyValueSupplier newValSupplier = createSupplier(desc.context(), desc.type(), newValColIdx, hasProps, false, true);
            sel = DmlAstUtils.selectForUpdate((GridSqlUpdate) stmt, errKeysPos);
            return UpdatePlan.forUpdate(gridTbl, colNames, colTypes, newValSupplier, valColIdx, sel.getSQL());
        } else {
            sel = DmlAstUtils.selectForDelete((GridSqlDelete) stmt, errKeysPos);
            return UpdatePlan.forDelete(gridTbl, sel.getSQL());
        }
    }
}
Also used : GridSqlDelete(org.apache.ignite.internal.processors.query.h2.sql.GridSqlDelete) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect) GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) Column(org.h2.table.Column) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) GridSqlTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlUpdate(org.apache.ignite.internal.processors.query.h2.sql.GridSqlUpdate)

Example 28 with Row

use of org.h2.result.Row in project ignite by apache.

the class GridH2TreeIndex method findFirstOrLast.

/** {@inheritDoc} */
@Override
public Cursor findFirstOrLast(Session ses, boolean first) {
    try {
        int seg = threadLocalSegment();
        IgniteTree t = treeForRead(seg);
        GridH2Row row = (GridH2Row) (first ? t.findFirst() : t.findLast());
        return new SingleRowCursor(row);
    } catch (IgniteCheckedException e) {
        throw DbException.convert(e);
    }
}
Also used : IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteTree(org.apache.ignite.internal.util.IgniteTree) SingleRowCursor(org.h2.index.SingleRowCursor)

Example 29 with Row

use of org.h2.result.Row in project ignite by apache.

the class GridReduceQueryExecutor method query.

/**
     * @param schemaName Schema name.
     * @param qry Query.
     * @param keepBinary Keep binary.
     * @param enforceJoinOrder Enforce join order of tables.
     * @param timeoutMillis Timeout in milliseconds.
     * @param cancel Query cancel.
     * @param params Query parameters.
     * @param parts Partitions.
     * @return Rows iterator.
     */
public Iterator<List<?>> query(String schemaName, GridCacheTwoStepQuery qry, boolean keepBinary, boolean enforceJoinOrder, int timeoutMillis, GridQueryCancel cancel, Object[] params, final int[] parts) {
    if (F.isEmpty(params))
        params = EMPTY_PARAMS;
    final boolean isReplicatedOnly = qry.isReplicatedOnly();
    // Fail if all caches are replicated and explicit partitions are set.
    for (int attempt = 0; ; attempt++) {
        if (attempt != 0) {
            try {
                // Wait for exchange.
                Thread.sleep(attempt * 10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new CacheException("Query was interrupted.", e);
            }
        }
        final long qryReqId = qryIdGen.incrementAndGet();
        final ReduceQueryRun r = new ReduceQueryRun(qryReqId, qry.originalSql(), schemaName, h2.connectionForSchema(schemaName), qry.mapQueries().size(), qry.pageSize(), U.currentTimeMillis(), cancel);
        AffinityTopologyVersion topVer = h2.readyTopologyVersion();
        List<Integer> cacheIds = qry.cacheIds();
        Collection<ClusterNode> nodes = null;
        // Explicit partition mapping for unstable topology.
        Map<ClusterNode, IntArray> partsMap = null;
        // Explicit partitions mapping for query.
        Map<ClusterNode, IntArray> qryMap = null;
        // Partitions are not supported for queries over all replicated caches.
        if (parts != null) {
            boolean replicatedOnly = true;
            for (Integer cacheId : cacheIds) {
                if (!cacheContext(cacheId).isReplicated()) {
                    replicatedOnly = false;
                    break;
                }
            }
            if (replicatedOnly)
                throw new CacheException("Partitions are not supported for replicated caches");
        }
        if (qry.isLocal())
            nodes = singletonList(ctx.discovery().localNode());
        else {
            if (isPreloadingActive(cacheIds)) {
                if (isReplicatedOnly)
                    nodes = replicatedUnstableDataNodes(cacheIds);
                else {
                    partsMap = partitionedUnstableDataNodes(cacheIds);
                    if (partsMap != null) {
                        qryMap = narrowForQuery(partsMap, parts);
                        nodes = qryMap == null ? null : qryMap.keySet();
                    }
                }
            } else {
                qryMap = stableDataNodes(isReplicatedOnly, topVer, cacheIds, parts);
                if (qryMap != null)
                    nodes = qryMap.keySet();
            }
            if (nodes == null)
                // Retry.
                continue;
            assert !nodes.isEmpty();
            if (isReplicatedOnly || qry.explain()) {
                ClusterNode locNode = ctx.discovery().localNode();
                // Always prefer local node if possible.
                if (nodes.contains(locNode))
                    nodes = singletonList(locNode);
                else {
                    // Select random data node to run query on a replicated data or
                    // get EXPLAIN PLAN from a single node.
                    nodes = singletonList(F.rand(nodes));
                }
            }
        }
        int tblIdx = 0;
        final boolean skipMergeTbl = !qry.explain() && qry.skipMergeTable();
        final int segmentsPerIndex = qry.explain() || isReplicatedOnly ? 1 : findFirstPartitioned(cacheIds).config().getQueryParallelism();
        int replicatedQrysCnt = 0;
        for (GridCacheSqlQuery mapQry : qry.mapQueries()) {
            GridMergeIndex idx;
            if (!skipMergeTbl) {
                GridMergeTable tbl;
                try {
                    tbl = createMergeTable(r.connection(), mapQry, qry.explain());
                } catch (IgniteCheckedException e) {
                    throw new IgniteException(e);
                }
                idx = tbl.getMergeIndex();
                fakeTable(r.connection(), tblIdx++).innerTable(tbl);
            } else
                idx = GridMergeIndexUnsorted.createDummy(ctx);
            // If the query has only replicated tables, we have to run it on a single node only.
            if (!mapQry.isPartitioned()) {
                ClusterNode node = F.rand(nodes);
                mapQry.node(node.id());
                replicatedQrysCnt++;
                // Replicated tables can have only 1 segment.
                idx.setSources(singletonList(node), 1);
            } else
                idx.setSources(nodes, segmentsPerIndex);
            idx.setPageSize(r.pageSize());
            r.indexes().add(idx);
        }
        r.latch(new CountDownLatch(isReplicatedOnly ? 1 : (r.indexes().size() - replicatedQrysCnt) * nodes.size() * segmentsPerIndex + replicatedQrysCnt));
        runs.put(qryReqId, r);
        try {
            cancel.checkCancelled();
            if (ctx.clientDisconnected()) {
                throw new CacheException("Query was cancelled, client node disconnected.", new IgniteClientDisconnectedException(ctx.cluster().clientReconnectFuture(), "Client node disconnected."));
            }
            List<GridCacheSqlQuery> mapQrys = qry.mapQueries();
            if (qry.explain()) {
                mapQrys = new ArrayList<>(qry.mapQueries().size());
                for (GridCacheSqlQuery mapQry : qry.mapQueries()) mapQrys.add(new GridCacheSqlQuery("EXPLAIN " + mapQry.query()).parameterIndexes(mapQry.parameterIndexes()));
            }
            final boolean distributedJoins = qry.distributedJoins();
            final Collection<ClusterNode> finalNodes = nodes;
            cancel.set(new Runnable() {

                @Override
                public void run() {
                    send(finalNodes, new GridQueryCancelRequest(qryReqId), null, false);
                }
            });
            boolean retry = false;
            // Always enforce join order on map side to have consistent behavior.
            int flags = GridH2QueryRequest.FLAG_ENFORCE_JOIN_ORDER;
            if (distributedJoins)
                flags |= GridH2QueryRequest.FLAG_DISTRIBUTED_JOINS;
            if (qry.isLocal())
                flags |= GridH2QueryRequest.FLAG_IS_LOCAL;
            if (qry.explain())
                flags |= GridH2QueryRequest.FLAG_EXPLAIN;
            if (isReplicatedOnly)
                flags |= GridH2QueryRequest.FLAG_REPLICATED;
            GridH2QueryRequest req = new GridH2QueryRequest().requestId(qryReqId).topologyVersion(topVer).pageSize(r.pageSize()).caches(qry.cacheIds()).tables(distributedJoins ? qry.tables() : null).partitions(convert(partsMap)).queries(mapQrys).parameters(params).flags(flags).timeout(timeoutMillis).schemaName(schemaName);
            if (send(nodes, req, parts == null ? null : new ExplicitPartitionsSpecializer(qryMap), false)) {
                awaitAllReplies(r, nodes, cancel);
                Object state = r.state();
                if (state != null) {
                    if (state instanceof CacheException) {
                        CacheException err = (CacheException) state;
                        if (err.getCause() instanceof IgniteClientDisconnectedException)
                            throw err;
                        if (wasCancelled(err))
                            // Throw correct exception.
                            throw new QueryCancelledException();
                        throw new CacheException("Failed to run map query remotely.", err);
                    }
                    if (state instanceof AffinityTopologyVersion) {
                        retry = true;
                        // If remote node asks us to retry then we have outdated full partition map.
                        h2.awaitForReadyTopologyVersion((AffinityTopologyVersion) state);
                    }
                }
            } else
                // Send failed.
                retry = true;
            Iterator<List<?>> resIter = null;
            if (!retry) {
                if (skipMergeTbl) {
                    List<List<?>> res = new ArrayList<>();
                    // Simple UNION ALL can have multiple indexes.
                    for (GridMergeIndex idx : r.indexes()) {
                        Cursor cur = idx.findInStream(null, null);
                        while (cur.next()) {
                            Row row = cur.get();
                            int cols = row.getColumnCount();
                            List<Object> resRow = new ArrayList<>(cols);
                            for (int c = 0; c < cols; c++) resRow.add(row.getValue(c).getObject());
                            res.add(resRow);
                        }
                    }
                    resIter = res.iterator();
                } else {
                    cancel.checkCancelled();
                    UUID locNodeId = ctx.localNodeId();
                    H2Utils.setupConnection(r.connection(), false, enforceJoinOrder);
                    GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, qryReqId, REDUCE).pageSize(r.pageSize()).distributedJoinMode(OFF));
                    try {
                        if (qry.explain())
                            return explainPlan(r.connection(), qry, params);
                        GridCacheSqlQuery rdc = qry.reduceQuery();
                        ResultSet res = h2.executeSqlQueryWithTimer(r.connection(), rdc.query(), F.asList(rdc.parameters(params)), // The statement will cache some extra thread local objects.
                        false, timeoutMillis, cancel);
                        resIter = new H2FieldsIterator(res);
                    } finally {
                        GridH2QueryContext.clearThreadLocal();
                    }
                }
            }
            if (retry) {
                if (Thread.currentThread().isInterrupted())
                    throw new IgniteInterruptedCheckedException("Query was interrupted.");
                continue;
            }
            return new GridQueryCacheObjectsIterator(resIter, h2.objectContext(), keepBinary);
        } catch (IgniteCheckedException | RuntimeException e) {
            U.closeQuiet(r.connection());
            if (e instanceof CacheException) {
                if (wasCancelled((CacheException) e))
                    throw new CacheException("Failed to run reduce query locally.", new QueryCancelledException());
                throw (CacheException) e;
            }
            Throwable cause = e;
            if (e instanceof IgniteCheckedException) {
                Throwable disconnectedErr = ((IgniteCheckedException) e).getCause(IgniteClientDisconnectedException.class);
                if (disconnectedErr != null)
                    cause = disconnectedErr;
            }
            throw new CacheException("Failed to run reduce query locally.", cause);
        } finally {
            // Make sure any activity related to current attempt is cancelled.
            cancelRemoteQueriesIfNeeded(nodes, r, qryReqId, qry.distributedJoins());
            if (!runs.remove(qryReqId, r))
                U.warn(log, "Query run was already removed: " + qryReqId);
            if (!skipMergeTbl) {
                for (int i = 0, mapQrys = qry.mapQueries().size(); i < mapQrys; i++) // Drop all merge tables.
                fakeTable(null, i).innerTable(null);
            }
        }
    }
}
Also used : GridQueryCancelRequest(org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryCancelRequest) CacheException(javax.cache.CacheException) ArrayList(java.util.ArrayList) H2FieldsIterator(org.apache.ignite.internal.processors.query.h2.H2FieldsIterator) Cursor(org.h2.index.Cursor) GridQueryCacheObjectsIterator(org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator) IgniteInterruptedCheckedException(org.apache.ignite.internal.IgniteInterruptedCheckedException) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IntArray(org.h2.util.IntArray) IgniteException(org.apache.ignite.IgniteException) ResultSet(java.sql.ResultSet) Collections.singletonList(java.util.Collections.singletonList) GridIntList(org.apache.ignite.internal.util.GridIntList) List(java.util.List) ArrayList(java.util.ArrayList) GridCacheSqlQuery(org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery) UUID(java.util.UUID) GridH2QueryContext(org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext) ClusterNode(org.apache.ignite.cluster.ClusterNode) AffinityTopologyVersion(org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion) IgniteClientDisconnectedException(org.apache.ignite.IgniteClientDisconnectedException) GridH2QueryRequest(org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2QueryRequest) CountDownLatch(java.util.concurrent.CountDownLatch) Row(org.h2.result.Row) QueryCancelledException(org.apache.ignite.cache.query.QueryCancelledException)

Aggregations

Value (org.h2.value.Value)12 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)8 ArrayList (java.util.ArrayList)4 CacheException (javax.cache.CacheException)4 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)4 H2PkHashIndex (org.apache.ignite.internal.processors.query.h2.database.H2PkHashIndex)4 Index (org.h2.index.Index)4 ResultSet (java.sql.ResultSet)3 UUID (java.util.UUID)3 BinaryObject (org.apache.ignite.binary.BinaryObject)3 GridH2ValueMessage (org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessage)3 SearchRow (org.h2.result.SearchRow)3 Column (org.h2.table.Column)3 IndexColumn (org.h2.table.IndexColumn)3 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 Random (java.util.Random)2 Lock (java.util.concurrent.locks.Lock)2 ReadWriteLock (java.util.concurrent.locks.ReadWriteLock)2 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)2