Search in sources :

Example 46 with AND

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.

the class SqlAstTraverser method lookForPartitionedJoin.

/**
 * Traverse AST while join operation isn't found. Check it if found.
 *
 * @param ast AST item to check recursively.
 * @param upWhere Where condition that applies to this ast.
 */
private void lookForPartitionedJoin(GridSqlAst ast, GridSqlAst upWhere) {
    if (ast == null)
        return;
    GridSqlJoin join = null;
    GridSqlAst where = null;
    if (ast instanceof GridSqlJoin) {
        join = (GridSqlJoin) ast;
        where = upWhere;
    } else if (ast instanceof GridSqlSelect) {
        GridSqlSelect select = (GridSqlSelect) ast;
        if (select.from() instanceof GridSqlJoin) {
            join = (GridSqlJoin) select.from();
            where = select.where();
        }
    } else if (ast instanceof GridSqlSubquery)
        hasSubQueries = true;
    else if (ast instanceof GridSqlTable)
        hasPartitionedTables |= ((GridSqlTable) ast).dataTable().isPartitioned();
    // No joins on this level. Traverse AST deeper.
    if (join == null) {
        for (int i = 0; i < ast.size(); i++) lookForPartitionedJoin(ast.child(i), null);
        return;
    }
    // Check WHERE clause first.
    lookForPartitionedJoin(where, null);
    // Check left side of join.
    GridSqlTable leftTable = getTable(join.leftTable());
    GridH2Table left = null;
    // Left side of join is a subquery.
    if (leftTable == null) {
        hasSubQueries = true;
        // Check subquery on left side.
        lookForPartitionedJoin(join.leftTable(), where);
    } else {
        left = leftTable.dataTable();
        // Data table is NULL for views.
        if (left != null && left.isPartitioned())
            hasPartitionedTables = true;
    }
    // Check right side of join.
    GridSqlTable rightTable = getTable(join.rightTable());
    // Right side of join is a subquery.
    if (rightTable == null) {
        hasSubQueries = true;
        // Check subquery and return (can't exctract more info there).
        lookForPartitionedJoin(join.rightTable(), where);
        return;
    }
    GridH2Table right = rightTable.dataTable();
    if (right != null && right.isPartitioned())
        hasPartitionedTables = true;
    // Skip check of views.
    if (left == null || right == null)
        return;
    if (join.isLeftOuter() && !left.isPartitioned() && right.isPartitioned())
        hasOuterJoinReplicatedPartitioned = true;
    // Skip check if at least one of tables isn't partitioned.
    if (!(left.isPartitioned() && right.isPartitioned()))
        return;
    if (!distributedJoins)
        checkPartitionedJoin(join, where, left, right, log);
}
Also used : GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)

Example 47 with AND

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.

the class NoneOrSinglePartitionsQueryOptimizationsTest method runQuery.

/**
 * Runs query and checks that given sql query returns expect rows count.
 *
 * @param sqlQry SQL query
 * @param expResCnt Expected result rows count.
 * @param expMergeTbl Flag that signals that merge table is expected to be created.
 * @param explainSize Explain plan response size.
 * @param expOriginalQry Flag that signals that orignial sql query is expected as map query.
 * @throws Exception If failed.s
 */
@SuppressWarnings({ "ThrowableNotThrown", "unchecked" })
private void runQuery(String sqlQry, int expResCnt, boolean expMergeTbl, boolean expOriginalQry, int explainSize, Object... args) throws Exception {
    TestCommunicationSpi commSpi = (TestCommunicationSpi) grid(NODES_COUNT).configuration().getCommunicationSpi();
    commSpi.resetQueries();
    IgniteInternalFuture res = GridTestUtils.runAsync(() -> {
        QueryCursor cursor = orgCache.query(new SqlFieldsQuery(sqlQry).setArgs(args));
        Iterable iter = U.field(cursor, "iterExec");
        Iterator innerIter = U.field(iter.iterator(), "iter");
        if (expMergeTbl)
            assertTrue(innerIter instanceof H2ResultSetIterator);
        else
            assertTrue(innerIter instanceof ReduceIndexIterator);
        List<List<?>> all = new ArrayList<>();
        while (innerIter.hasNext()) all.add((List) innerIter.next());
        return all;
    });
    List<List<?>> rows = (List<List<?>>) res.get(RES_RETRIEVAL_TIMEOUT);
    assertNotNull(rows);
    assertEquals(expResCnt, rows.size());
    int mapQueriesCnt = commSpi.mapQueries.size();
    if (expOriginalQry) {
        assertEquals(1, mapQueriesCnt);
        assertEquals(sqlQry, commSpi.mapQueries.get(0));
    } else {
        for (String mapQry : commSpi.mapQueries) assertNotEquals(sqlQry, mapQry);
    }
    // Test explain query.
    QueryCursor explainCursor = orgCache.query(new SqlFieldsQuery("explain " + sqlQry).setArgs(args));
    List<List<?>> explainRes = explainCursor.getAll();
    assertEquals(explainSize, explainRes.size());
    if (expMergeTbl)
        assertTrue(((String) explainRes.get(explainRes.size() - 1).get(0)).contains(GridSqlQuerySplitter.mergeTableIdentifier(0)));
}
Also used : H2ResultSetIterator(org.apache.ignite.internal.processors.query.h2.H2ResultSetIterator) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) H2ResultSetIterator(org.apache.ignite.internal.processors.query.h2.H2ResultSetIterator) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) QueryCursor(org.apache.ignite.cache.query.QueryCursor)

Example 48 with AND

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.

the class DmlStatementsProcessor method rowToKeyValue.

/**
     * Convert row presented as an array of Objects into key-value pair to be inserted to cache.
     * @param cctx Cache context.
     * @param row Row to process.
     * @param plan Update plan.
     * @throws IgniteCheckedException if failed.
     */
@SuppressWarnings({ "unchecked", "ConstantConditions", "ResultOfMethodCallIgnored" })
private IgniteBiTuple<?, ?> rowToKeyValue(GridCacheContext cctx, List<?> row, UpdatePlan plan) throws IgniteCheckedException {
    GridH2RowDescriptor rowDesc = plan.tbl.rowDescriptor();
    GridQueryTypeDescriptor desc = rowDesc.type();
    Object key = plan.keySupplier.apply(row);
    if (QueryUtils.isSqlType(desc.keyClass())) {
        assert plan.keyColIdx != -1;
        key = convert(key, rowDesc, desc.keyClass(), plan.colTypes[plan.keyColIdx]);
    }
    Object val = plan.valSupplier.apply(row);
    if (QueryUtils.isSqlType(desc.valueClass())) {
        assert plan.valColIdx != -1;
        val = convert(val, rowDesc, desc.valueClass(), plan.colTypes[plan.valColIdx]);
    }
    if (key == null)
        throw new IgniteSQLException("Key for INSERT or MERGE must not be null", IgniteQueryErrorCode.NULL_KEY);
    if (val == null)
        throw new IgniteSQLException("Value for INSERT or MERGE must not be null", IgniteQueryErrorCode.NULL_VALUE);
    Map<String, Object> newColVals = new HashMap<>();
    for (int i = 0; i < plan.colNames.length; i++) {
        if (i == plan.keyColIdx || i == plan.valColIdx)
            continue;
        String colName = plan.colNames[i];
        GridQueryProperty prop = desc.property(colName);
        assert prop != null;
        Class<?> expCls = prop.type();
        newColVals.put(colName, convert(row.get(i), rowDesc, expCls, plan.colTypes[i]));
    }
    // We update columns in the order specified by the table for a reason - table's
    // column order preserves their precedence for correct update of nested properties.
    Column[] cols = plan.tbl.getColumns();
    // First 3 columns are _key, _val and _ver. Skip 'em.
    for (int i = DEFAULT_COLUMNS_COUNT; i < cols.length; i++) {
        if (plan.tbl.rowDescriptor().isKeyValueOrVersionColumn(i))
            continue;
        String colName = cols[i].getName();
        if (!newColVals.containsKey(colName))
            continue;
        Object colVal = newColVals.get(colName);
        desc.setValue(colName, key, val, colVal);
    }
    if (cctx.binaryMarshaller()) {
        if (key instanceof BinaryObjectBuilder)
            key = ((BinaryObjectBuilder) key).build();
        if (val instanceof BinaryObjectBuilder)
            val = ((BinaryObjectBuilder) val).build();
    }
    return new IgniteBiTuple<>(key, val);
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) GridBoundedConcurrentLinkedHashMap(org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashMap) IgniteBiTuple(org.apache.ignite.lang.IgniteBiTuple) GridQueryTypeDescriptor(org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor) GridQueryProperty(org.apache.ignite.internal.processors.query.GridQueryProperty) GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) Column(org.h2.table.Column) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) BinaryObject(org.apache.ignite.binary.BinaryObject) BinaryObjectBuilder(org.apache.ignite.binary.BinaryObjectBuilder)

Example 49 with AND

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.

the class GridH2TableSelfTest method testTable.

/**
     * Simple table test.
     *
     * @throws Exception If failed.
     */
public void testTable() throws Exception {
    // Test insert.
    long x = MAX_X;
    Random rnd = new Random();
    while (x-- > 0) {
        UUID id = UUID.randomUUID();
        GridH2Row row = row(id, System.currentTimeMillis(), rnd.nextBoolean() ? id.toString() : UUID.randomUUID().toString(), rnd.nextInt(100));
        tbl.doUpdate(row, false);
    }
    assertEquals(MAX_X, tbl.getRowCountApproximation());
    assertEquals(MAX_X, tbl.getRowCount(null));
    for (GridH2IndexBase idx : tbl.indexes()) {
        assertEquals(MAX_X, idx.getRowCountApproximation());
        assertEquals(MAX_X, idx.getRowCount(null));
    }
    // Check correct rows order.
    checkOrdered((GridH2TreeIndex) tbl.indexes().get(0), new Comparator<SearchRow>() {

        @Override
        public int compare(SearchRow o1, SearchRow o2) {
            UUID id1 = (UUID) o1.getValue(0).getObject();
            UUID id2 = (UUID) o2.getValue(0).getObject();
            return id1.compareTo(id2);
        }
    });
    checkOrdered((GridH2TreeIndex) tbl.indexes().get(1), new Comparator<SearchRow>() {

        @Override
        public int compare(SearchRow o1, SearchRow o2) {
            Long x1 = (Long) o1.getValue(3).getObject();
            Long x2 = (Long) o2.getValue(3).getObject();
            int c = x2.compareTo(x1);
            if (c != 0)
                return c;
            Timestamp t1 = (Timestamp) o1.getValue(1).getObject();
            Timestamp t2 = (Timestamp) o2.getValue(1).getObject();
            return t1.compareTo(t2);
        }
    });
    checkOrdered((GridH2TreeIndex) tbl.indexes().get(2), new Comparator<SearchRow>() {

        @Override
        public int compare(SearchRow o1, SearchRow o2) {
            String s1 = (String) o1.getValue(2).getObject();
            String s2 = (String) o2.getValue(2).getObject();
            return s2.compareTo(s1);
        }
    });
    // Indexes data consistency.
    ArrayList<? extends Index> idxs = tbl.indexes();
    checkIndexesConsistent((ArrayList<Index>) idxs, null);
    // Check unique index.
    UUID id = UUID.randomUUID();
    UUID id2 = UUID.randomUUID();
    assertTrue(tbl.doUpdate(row(id, System.currentTimeMillis(), id.toString(), rnd.nextInt(100)), false));
    assertTrue(tbl.doUpdate(row(id2, System.currentTimeMillis(), id2.toString(), rnd.nextInt(100)), false));
    // Check index selection.
    checkQueryPlan(conn, "SELECT * FROM T", SCAN_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE ID IS NULL", PK_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE ID = RANDOM_UUID()", PK_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE ID > RANDOM_UUID()", PK_NAME);
    checkQueryPlan(conn, "SELECT * FROM T ORDER BY ID", PK_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE STR IS NULL", STR_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE STR = 'aaaa'", STR_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE STR > 'aaaa'", STR_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T ORDER BY STR DESC", STR_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE X IS NULL", NON_UNIQUE_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE X = 10000", NON_UNIQUE_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T WHERE X > 10000", NON_UNIQUE_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T ORDER BY X DESC", NON_UNIQUE_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T ORDER BY X DESC, T", NON_UNIQUE_IDX_NAME);
    checkQueryPlan(conn, "SELECT * FROM T ORDER BY T, X DESC", SCAN_IDX_NAME);
    // Simple queries.
    Statement s = conn.createStatement();
    ResultSet rs = s.executeQuery("select id from t where x between 0 and 100");
    int i = 0;
    while (rs.next()) i++;
    assertEquals(MAX_X + 2, i);
    // -----
    rs = s.executeQuery("select id from t where t is not null");
    i = 0;
    while (rs.next()) i++;
    assertEquals(MAX_X + 2, i);
    // ----
    int cnt = 10 + rnd.nextInt(25);
    long t = System.currentTimeMillis();
    for (i = 0; i < cnt; i++) {
        id = UUID.randomUUID();
        assertTrue(tbl.doUpdate(row(id, t, id.toString(), 51), false));
    }
    rs = s.executeQuery("select x, id from t where x = 51 limit " + cnt);
    i = 0;
    while (rs.next()) {
        assertEquals(51, rs.getInt(1));
        i++;
    }
    assertEquals(cnt, i);
}
Also used : PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Index(org.h2.index.Index) H2PkHashIndex(org.apache.ignite.internal.processors.query.h2.database.H2PkHashIndex) ValueString(org.h2.value.ValueString) Timestamp(java.sql.Timestamp) ValueTimestamp(org.h2.value.ValueTimestamp) Random(java.util.Random) ValueLong(org.h2.value.ValueLong) ResultSet(java.sql.ResultSet) UUID(java.util.UUID) SearchRow(org.h2.result.SearchRow)

Example 50 with AND

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.

the class UpdatePlanBuilder method planForInsert.

/**
     * Prepare update plan for INSERT or MERGE.
     *
     * @param stmt INSERT or MERGE statement.
     * @return Update plan.
     * @throws IgniteCheckedException if failed.
     */
@SuppressWarnings("ConstantConditions")
private static UpdatePlan planForInsert(GridSqlStatement stmt) throws IgniteCheckedException {
    GridSqlQuery sel;
    GridSqlElement target;
    GridSqlColumn[] cols;
    boolean isTwoStepSubqry;
    int rowsNum;
    GridSqlTable tbl;
    GridH2RowDescriptor desc;
    if (stmt instanceof GridSqlInsert) {
        GridSqlInsert ins = (GridSqlInsert) stmt;
        target = ins.into();
        tbl = gridTableForElement(target);
        desc = tbl.dataTable().rowDescriptor();
        cols = ins.columns();
        sel = DmlAstUtils.selectForInsertOrMerge(cols, ins.rows(), ins.query(), desc);
        isTwoStepSubqry = (ins.query() != null);
        rowsNum = isTwoStepSubqry ? 0 : ins.rows().size();
    } else if (stmt instanceof GridSqlMerge) {
        GridSqlMerge merge = (GridSqlMerge) stmt;
        target = merge.into();
        tbl = gridTableForElement(target);
        desc = tbl.dataTable().rowDescriptor();
        // This check also protects us from attempts to update key or its fields directly -
        // when no key except cache key can be used, it will serve only for uniqueness checks,
        // not for updates, and hence will allow putting new pairs only.
        // We don't quote _key and _val column names on CREATE TABLE, so they are always uppercase here.
        GridSqlColumn[] keys = merge.keys();
        if (keys.length != 1 || !desc.isKeyColumn(tbl.dataTable().getColumn(keys[0].columnName()).getColumnId()))
            throw new CacheException("SQL MERGE does not support arbitrary keys");
        cols = merge.columns();
        sel = DmlAstUtils.selectForInsertOrMerge(cols, merge.rows(), merge.query(), desc);
        isTwoStepSubqry = (merge.query() != null);
        rowsNum = isTwoStepSubqry ? 0 : merge.rows().size();
    } else
        throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION);
    // Let's set the flag only for subqueries that have their FROM specified.
    isTwoStepSubqry = (isTwoStepSubqry && (sel instanceof GridSqlUnion || (sel instanceof GridSqlSelect && ((GridSqlSelect) sel).from() != null)));
    int keyColIdx = -1;
    int valColIdx = -1;
    boolean hasKeyProps = false;
    boolean hasValProps = false;
    if (desc == null)
        throw new IgniteSQLException("Row descriptor undefined for table '" + tbl.dataTable().getName() + "'", IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR);
    GridCacheContext<?, ?> cctx = desc.context();
    String[] colNames = new String[cols.length];
    int[] colTypes = new int[cols.length];
    for (int i = 0; i < cols.length; i++) {
        GridSqlColumn col = cols[i];
        String colName = col.columnName();
        colNames[i] = colName;
        colTypes[i] = col.resultType().type();
        int colId = col.column().getColumnId();
        if (desc.isKeyColumn(colId)) {
            keyColIdx = i;
            continue;
        }
        if (desc.isValueColumn(colId)) {
            valColIdx = i;
            continue;
        }
        GridQueryProperty prop = desc.type().property(colName);
        assert prop != null : "Property '" + colName + "' not found.";
        if (prop.key())
            hasKeyProps = true;
        else
            hasValProps = true;
    }
    KeyValueSupplier keySupplier = createSupplier(cctx, desc.type(), keyColIdx, hasKeyProps, true, false);
    KeyValueSupplier valSupplier = createSupplier(cctx, desc.type(), valColIdx, hasValProps, false, false);
    if (stmt instanceof GridSqlMerge)
        return UpdatePlan.forMerge(tbl.dataTable(), colNames, colTypes, keySupplier, valSupplier, keyColIdx, valColIdx, sel.getSQL(), !isTwoStepSubqry, rowsNum);
    else
        return UpdatePlan.forInsert(tbl.dataTable(), colNames, colTypes, keySupplier, valSupplier, keyColIdx, valColIdx, sel.getSQL(), !isTwoStepSubqry, rowsNum);
}
Also used : GridSqlMerge(org.apache.ignite.internal.processors.query.h2.sql.GridSqlMerge) GridSqlUnion(org.apache.ignite.internal.processors.query.h2.sql.GridSqlUnion) CacheException(javax.cache.CacheException) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect) GridSqlQuery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery) GridQueryProperty(org.apache.ignite.internal.processors.query.GridQueryProperty) GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) GridSqlTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlInsert(org.apache.ignite.internal.processors.query.h2.sql.GridSqlInsert)

Aggregations

IgniteCheckedException (org.apache.ignite.IgniteCheckedException)37 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)33 ArrayList (java.util.ArrayList)26 GridH2Table (org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)25 List (java.util.List)22 IgniteException (org.apache.ignite.IgniteException)21 SQLException (java.sql.SQLException)15 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)15 GridH2RowDescriptor (org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor)13 HashMap (java.util.HashMap)12 Column (org.h2.table.Column)12 LinkedHashMap (java.util.LinkedHashMap)11 GridQueryTypeDescriptor (org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor)11 Index (org.h2.index.Index)11 PreparedStatement (java.sql.PreparedStatement)9 SqlFieldsQuery (org.apache.ignite.cache.query.SqlFieldsQuery)9 GridQueryProperty (org.apache.ignite.internal.processors.query.GridQueryProperty)9 UpdatePlan (org.apache.ignite.internal.processors.query.h2.dml.UpdatePlan)9 GridSqlColumn (org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn)9 GridSqlElement (org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement)9