Search in sources :

Example 6 with GridQueryFieldMetadata

use of org.apache.ignite.internal.processors.query.GridQueryFieldMetadata in project ignite by apache.

the class IgniteCacheAbstractFieldsQuerySelfTest method testExecuteWithMetaData.

/**
 * @throws Exception If failed.
 */
@Test
public void testExecuteWithMetaData() throws Exception {
    QueryCursorImpl<List<?>> cursor = (QueryCursorImpl<List<?>>) personCache.query(sqlFieldsQuery(String.format("select p._KEY, p.name, p.age, o.name " + "from \"%s\".Person p, \"%s\".Organization o where p.orgId = o.id", personCache.getName(), orgCache.getName())));
    Collection<GridQueryFieldMetadata> meta = cursor.fieldsMeta();
    assertNotNull(meta);
    assertEquals(4, meta.size());
    Iterator<GridQueryFieldMetadata> metaIt = meta.iterator();
    assertNotNull(metaIt);
    assert metaIt.hasNext();
    GridQueryFieldMetadata field = metaIt.next();
    assertNotNull(field);
    assertEquals(personCache.getName(), field.schemaName());
    assertEquals("PERSON", field.typeName());
    assertEquals("_KEY", field.fieldName());
    assertEquals(Object.class.getName(), field.fieldTypeName());
    assert metaIt.hasNext();
    field = metaIt.next();
    assertNotNull(field);
    assertEquals(personCache.getName(), field.schemaName());
    assertEquals("PERSON", field.typeName());
    assertEquals("NAME", field.fieldName());
    assertEquals(String.class.getName(), field.fieldTypeName());
    assert metaIt.hasNext();
    field = metaIt.next();
    assertNotNull(field);
    assertEquals(personCache.getName(), field.schemaName());
    assertEquals("PERSON", field.typeName());
    assertEquals("AGE", field.fieldName());
    assertEquals(Integer.class.getName(), field.fieldTypeName());
    assert metaIt.hasNext();
    field = metaIt.next();
    assert field != null;
    assertNotNull(field);
    assertEquals(orgCache.getName(), field.schemaName());
    assertEquals("ORGANIZATION", field.typeName());
    assertEquals("NAME", field.fieldName());
    assertEquals(String.class.getName(), field.fieldTypeName());
    assert !metaIt.hasNext();
    List<List<?>> res = cursor.getAll();
    dedup(res);
    assertEquals(3, res.size());
    Collections.sort(res, new Comparator<List<?>>() {

        @Override
        public int compare(List<?> row1, List<?> row2) {
            return ((Integer) row1.get(2)).compareTo((Integer) row2.get(2));
        }
    });
    int cnt = 0;
    for (List<?> row : res) {
        assert row.size() == 4;
        if (cnt == 0) {
            assertEquals(new AffinityKey<>("p1", "o1"), row.get(0));
            assertEquals("John White", row.get(1));
            assertEquals(25, row.get(2));
            assertEquals("A", row.get(3));
        } else if (cnt == 1) {
            assertEquals(new AffinityKey<>("p2", "o1"), row.get(0));
            assertEquals("Joe Black", row.get(1));
            assertEquals(35, row.get(2));
            assertEquals("A", row.get(3));
        }
        if (cnt == 2) {
            assertEquals(new AffinityKey<>("p3", "o2"), row.get(0));
            assertEquals("Mike Green", row.get(1));
            assertEquals(40, row.get(2));
            assertEquals("B", row.get(3));
        }
        cnt++;
    }
    assertEquals(3, cnt);
}
Also used : GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) ArrayList(java.util.ArrayList) List(java.util.List) AffinityKey(org.apache.ignite.cache.affinity.AffinityKey) GridCommonAbstractTest(org.apache.ignite.testframework.junits.common.GridCommonAbstractTest) Test(org.junit.Test)

Example 7 with GridQueryFieldMetadata

use of org.apache.ignite.internal.processors.query.GridQueryFieldMetadata in project ignite by apache.

the class IgniteCacheAbstractFieldsQuerySelfTest method testDecimalColumnScaleAndPrecision.

/**
 * Test that scale and precision returned correctly for Decimal column in result set:
 *
 * 1. Start node;
 * 2. Create table with Decimal(3,0) column;
 * 3. Insert a new row into the table;
 * 4. Execute select with decimal row;
 * 5. Check that selected decimal column has precision 3 and scale 0.
 *
 * @throws Exception If failed.
 */
@Test
public void testDecimalColumnScaleAndPrecision() throws Exception {
    QueryEntity qeWithPrecision = new QueryEntity().setKeyType("java.lang.Long").setValueType("TestType").addQueryField("age", "java.math.BigDecimal", "age").setFieldsPrecision(ImmutableMap.of("age", 3)).setFieldsScale(ImmutableMap.of("age", 0));
    grid(0).getOrCreateCache(cacheConfiguration().setName("cacheWithDecimalPrecisionAndScale").setQueryEntities(Collections.singleton(qeWithPrecision)));
    GridQueryProcessor qryProc = grid(0).context().query();
    qryProc.querySqlFields(new SqlFieldsQuery("INSERT INTO TestType(_key, age) VALUES(?, ?)").setSchema("cacheWithDecimalPrecisionAndScale").setArgs(1, new BigDecimal(160)), true);
    QueryCursorImpl<List<?>> cursor = (QueryCursorImpl<List<?>>) qryProc.querySqlFields(new SqlFieldsQuery("SELECT age FROM TestType").setSchema("cacheWithDecimalPrecisionAndScale"), true);
    List<GridQueryFieldMetadata> fieldsMeta = cursor.fieldsMeta();
    assertEquals(1, fieldsMeta.size());
    GridQueryFieldMetadata meta = fieldsMeta.get(0);
    assertEquals(3, meta.precision());
    assertEquals(0, meta.scale());
}
Also used : GridQueryProcessor(org.apache.ignite.internal.processors.query.GridQueryProcessor) GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) ArrayList(java.util.ArrayList) List(java.util.List) QueryEntity(org.apache.ignite.cache.QueryEntity) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) BigDecimal(java.math.BigDecimal) GridCommonAbstractTest(org.apache.ignite.testframework.junits.common.GridCommonAbstractTest) Test(org.junit.Test)

Example 8 with GridQueryFieldMetadata

use of org.apache.ignite.internal.processors.query.GridQueryFieldMetadata 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 9 with GridQueryFieldMetadata

use of org.apache.ignite.internal.processors.query.GridQueryFieldMetadata in project ignite by apache.

the class GridSubqueryJoinOptimizerSelfTest method check.

/**
 * @param sql Sql.
 * @param expSelectClauses Expected select clauses.
 */
private void check(String sql, int expSelectClauses) {
    optimizationEnabled(false);
    FieldsQueryCursor<List<?>> qry = cache.query(new SqlFieldsQuery(sql));
    List<GridQueryFieldMetadata> expMetaList = ((QueryCursorEx<List<?>>) qry).fieldsMeta();
    List<List<?>> exp = qry.getAll();
    exp.sort(ROW_COMPARATOR);
    optimizationEnabled(true);
    FieldsQueryCursor<List<?>> optQry = cache.query(new SqlFieldsQuery(sql).setEnforceJoinOrder(true));
    List<GridQueryFieldMetadata> actMetaList = ((QueryCursorEx<List<?>>) optQry).fieldsMeta();
    List<List<?>> act = optQry.getAll();
    act.sort(ROW_COMPARATOR);
    Assert.assertEquals("Result set mismatch", exp, act);
    List<String> expFieldTypes = new ArrayList<>();
    List<String> actualFieldTypes = new ArrayList<>();
    for (int i = 0; i < expMetaList.size(); i++) {
        GridQueryFieldMetadata expMeta = expMetaList.get(i);
        GridQueryFieldMetadata actMeta = actMetaList.get(i);
        expFieldTypes.add(expMeta.fieldName() + ":" + expMeta.fieldTypeName());
        actualFieldTypes.add(actMeta.fieldName() + ":" + actMeta.fieldTypeName());
    }
    Assert.assertEquals("Result set field names or field types mismatch", expFieldTypes, actualFieldTypes);
    String plan = cache.query(new SqlFieldsQuery("explain " + sql)).getAll().get(0).get(0).toString();
    System.out.println(plan);
    int actCnt = countEntries(plan, "SELECT");
    Assert.assertEquals(String.format("SELECT-clause count mismatch: exp=%d, act=%d, plan=[%s]", expSelectClauses, actCnt, plan), expSelectClauses, actCnt);
}
Also used : QueryCursorEx(org.apache.ignite.internal.processors.cache.query.QueryCursorEx) ArrayList(java.util.ArrayList) GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) ArrayList(java.util.ArrayList) List(java.util.List) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery)

Example 10 with GridQueryFieldMetadata

use of org.apache.ignite.internal.processors.query.GridQueryFieldMetadata in project ignite by apache.

the class OdbcRequestHandler method getResultMeta.

/**
 * {@link OdbcQueryGetQueryMetaRequest} command handler.
 * Returns metadata for a columns of the result set.
 *
 * @param req Get resultset metadata request.
 * @return Response.
 */
private ClientListenerResponse getResultMeta(OdbcQueryGetResultsetMetaRequest req) {
    try {
        String sql = OdbcEscapeUtils.parse(req.query());
        String schema = OdbcUtils.prepareSchema(req.schema());
        SqlFieldsQueryEx qry = makeQuery(schema, sql);
        List<GridQueryFieldMetadata> columns = ctx.query().getIndexing().resultMetaData(schema, qry);
        Collection<OdbcColumnMeta> meta = OdbcUtils.convertMetadata(columns);
        OdbcQueryGetResultsetMetaResult res = new OdbcQueryGetResultsetMetaResult(meta);
        return new OdbcResponse(res);
    } catch (Exception e) {
        U.error(log, "Failed to get resultset metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
        return exceptionToResult(e);
    }
}
Also used : SqlFieldsQueryEx(org.apache.ignite.internal.processors.cache.query.SqlFieldsQueryEx) GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteException(org.apache.ignite.IgniteException) BatchUpdateException(java.sql.BatchUpdateException) IgniteInterruptedCheckedException(org.apache.ignite.internal.IgniteInterruptedCheckedException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException)

Aggregations

GridQueryFieldMetadata (org.apache.ignite.internal.processors.query.GridQueryFieldMetadata)17 ArrayList (java.util.ArrayList)11 List (java.util.List)10 SqlFieldsQuery (org.apache.ignite.cache.query.SqlFieldsQuery)10 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)7 SQLException (java.sql.SQLException)6 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)6 PreparedStatement (java.sql.PreparedStatement)4 GridCommonAbstractTest (org.apache.ignite.testframework.junits.common.GridCommonAbstractTest)4 Prepared (org.h2.command.Prepared)4 Test (org.junit.Test)4 Connection (java.sql.Connection)3 UUID (java.util.UUID)3 IgniteException (org.apache.ignite.IgniteException)3 QueryEntity (org.apache.ignite.cache.QueryEntity)3 GridCacheTwoStepQuery (org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery)3 QueryCursorEx (org.apache.ignite.internal.processors.cache.query.QueryCursorEx)3 GridQueryProcessor (org.apache.ignite.internal.processors.query.GridQueryProcessor)3 GridH2QueryContext (org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext)3 BigDecimal (java.math.BigDecimal)2