Search in sources :

Example 1 with ParameterSpecification

use of org.hibernate.param.ParameterSpecification in project hibernate-orm by hibernate.

the class HqlSqlWalker method postProcessInsert.

@Override
protected void postProcessInsert(AST insert) throws SemanticException, QueryException {
    InsertStatement insertStatement = (InsertStatement) insert;
    insertStatement.validate();
    SelectClause selectClause = insertStatement.getSelectClause();
    Queryable persister = insertStatement.getIntoClause().getQueryable();
    if (!insertStatement.getIntoClause().isExplicitIdInsertion()) {
        // the insert did not explicitly reference the id.  See if
        //		1) that is allowed
        //		2) whether we need to alter the SQL tree to account for id
        final IdentifierGenerator generator = persister.getIdentifierGenerator();
        if (!BulkInsertionCapableIdentifierGenerator.class.isInstance(generator)) {
            throw new QueryException("Invalid identifier generator encountered for implicit id handling as part of bulk insertions");
        }
        final BulkInsertionCapableIdentifierGenerator capableGenerator = BulkInsertionCapableIdentifierGenerator.class.cast(generator);
        if (!capableGenerator.supportsBulkInsertionIdentifierGeneration()) {
            throw new QueryException("Identifier generator reported it does not support implicit id handling as part of bulk insertions");
        }
        final String fragment = capableGenerator.determineBulkInsertionIdentifierGenerationSelectFragment(sessionFactoryHelper.getFactory().getDialect());
        if (fragment != null) {
            // we got a fragment from the generator, so alter the sql tree...
            //
            // first, wrap the fragment as a node
            AST fragmentNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, fragment);
            // next, rearrange the SQL tree to add the fragment node as the first select expression
            AST originalFirstSelectExprNode = selectClause.getFirstChild();
            selectClause.setFirstChild(fragmentNode);
            fragmentNode.setNextSibling(originalFirstSelectExprNode);
            // finally, prepend the id column name(s) to the insert-spec
            insertStatement.getIntoClause().prependIdColumnSpec();
        }
    }
    if (sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect()) {
        AST child = selectClause.getFirstChild();
        int i = 0;
        while (child != null) {
            if (child instanceof ParameterNode) {
                // infer the parameter type from the type listed in the INSERT INTO clause
                ((ParameterNode) child).setExpectedType(insertStatement.getIntoClause().getInsertionTypes()[selectClause.getParameterPositions().get(i)]);
                i++;
            }
            child = child.getNextSibling();
        }
    }
    final boolean includeVersionProperty = persister.isVersioned() && !insertStatement.getIntoClause().isExplicitVersionInsertion() && persister.isVersionPropertyInsertable();
    if (includeVersionProperty) {
        // We need to seed the version value as part of this bulk insert
        VersionType versionType = persister.getVersionType();
        AST versionValueNode = null;
        if (sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect()) {
            int[] sqlTypes = versionType.sqlTypes(sessionFactoryHelper.getFactory());
            if (sqlTypes == null || sqlTypes.length == 0) {
                throw new IllegalStateException(versionType.getClass() + ".sqlTypes() returns null or empty array");
            }
            if (sqlTypes.length > 1) {
                throw new IllegalStateException(versionType.getClass() + ".sqlTypes() returns > 1 element; only single-valued versions are allowed.");
            }
            versionValueNode = getASTFactory().create(HqlSqlTokenTypes.PARAM, "?");
            ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType);
            ((ParameterNode) versionValueNode).setHqlParameterSpecification(paramSpec);
            parameters.add(0, paramSpec);
            if (sessionFactoryHelper.getFactory().getDialect().requiresCastingOfParametersInSelectClause()) {
                // we need to wrtap the param in a cast()
                MethodNode versionMethodNode = (MethodNode) getASTFactory().create(HqlSqlTokenTypes.METHOD_CALL, "(");
                AST methodIdentNode = getASTFactory().create(HqlSqlTokenTypes.IDENT, "cast");
                versionMethodNode.addChild(methodIdentNode);
                versionMethodNode.initializeMethodNode(methodIdentNode, true);
                AST castExprListNode = getASTFactory().create(HqlSqlTokenTypes.EXPR_LIST, "exprList");
                methodIdentNode.setNextSibling(castExprListNode);
                castExprListNode.addChild(versionValueNode);
                versionValueNode.setNextSibling(getASTFactory().create(HqlSqlTokenTypes.IDENT, sessionFactoryHelper.getFactory().getDialect().getTypeName(sqlTypes[0])));
                processFunction(versionMethodNode, true);
                versionValueNode = versionMethodNode;
            }
        } else {
            if (isIntegral(versionType)) {
                try {
                    Object seedValue = versionType.seed(null);
                    versionValueNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, seedValue.toString());
                } catch (Throwable t) {
                    throw new QueryException("could not determine seed value for version on bulk insert [" + versionType + "]");
                }
            } else if (isDatabaseGeneratedTimestamp(versionType)) {
                String functionName = sessionFactoryHelper.getFactory().getDialect().getCurrentTimestampSQLFunctionName();
                versionValueNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, functionName);
            } else {
                throw new QueryException("cannot handle version type [" + versionType + "] on bulk inserts with dialects not supporting parameters in insert-select statements");
            }
        }
        AST currentFirstSelectExprNode = selectClause.getFirstChild();
        selectClause.setFirstChild(versionValueNode);
        versionValueNode.setNextSibling(currentFirstSelectExprNode);
        insertStatement.getIntoClause().prependVersionColumnSpec();
    }
    if (insertStatement.getIntoClause().isDiscriminated()) {
        String sqlValue = insertStatement.getIntoClause().getQueryable().getDiscriminatorSQLValue();
        AST discrimValue = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, sqlValue);
        insertStatement.getSelectClause().addChild(discrimValue);
    }
}
Also used : SelectClause(org.hibernate.hql.internal.ast.tree.SelectClause) AST(antlr.collections.AST) CollectionFilterKeyParameterSpecification(org.hibernate.param.CollectionFilterKeyParameterSpecification) ParameterSpecification(org.hibernate.param.ParameterSpecification) PositionalParameterSpecification(org.hibernate.param.PositionalParameterSpecification) VersionTypeSeedParameterSpecification(org.hibernate.param.VersionTypeSeedParameterSpecification) NamedParameterSpecification(org.hibernate.param.NamedParameterSpecification) VersionTypeSeedParameterSpecification(org.hibernate.param.VersionTypeSeedParameterSpecification) Queryable(org.hibernate.persister.entity.Queryable) InsertStatement(org.hibernate.hql.internal.ast.tree.InsertStatement) UserVersionType(org.hibernate.usertype.UserVersionType) VersionType(org.hibernate.type.VersionType) BulkInsertionCapableIdentifierGenerator(org.hibernate.id.BulkInsertionCapableIdentifierGenerator) QueryException(org.hibernate.QueryException) ParameterNode(org.hibernate.hql.internal.ast.tree.ParameterNode) MethodNode(org.hibernate.hql.internal.ast.tree.MethodNode) IdentifierGenerator(org.hibernate.id.IdentifierGenerator) BulkInsertionCapableIdentifierGenerator(org.hibernate.id.BulkInsertionCapableIdentifierGenerator)

Example 2 with ParameterSpecification

use of org.hibernate.param.ParameterSpecification in project hibernate-orm by hibernate.

the class BasicExecutor method doExecute.

protected int doExecute(QueryParameters parameters, SharedSessionContractImplementor session, String sql, List parameterSpecifications) throws HibernateException {
    BulkOperationCleanupAction action = new BulkOperationCleanupAction(session, persister);
    if (session.isEventSource()) {
        ((EventSource) session).getActionQueue().addAction(action);
    } else {
        action.getAfterTransactionCompletionProcess().doAfterTransactionCompletion(true, session);
    }
    PreparedStatement st = null;
    RowSelection selection = parameters.getRowSelection();
    try {
        try {
            st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement(sql, false);
            Iterator paramSpecItr = parameterSpecifications.iterator();
            int pos = 1;
            while (paramSpecItr.hasNext()) {
                final ParameterSpecification paramSpec = (ParameterSpecification) paramSpecItr.next();
                pos += paramSpec.bind(st, parameters, session, pos);
            }
            if (selection != null) {
                if (selection.getTimeout() != null) {
                    st.setQueryTimeout(selection.getTimeout());
                }
            }
            return session.getJdbcCoordinator().getResultSetReturn().executeUpdate(st);
        } finally {
            if (st != null) {
                session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(st);
                session.getJdbcCoordinator().afterStatementExecution();
            }
        }
    } catch (SQLException sqle) {
        throw session.getJdbcServices().getSqlExceptionHelper().convert(sqle, "could not execute update query", sql);
    }
}
Also used : BulkOperationCleanupAction(org.hibernate.action.internal.BulkOperationCleanupAction) ParameterSpecification(org.hibernate.param.ParameterSpecification) SQLException(java.sql.SQLException) Iterator(java.util.Iterator) PreparedStatement(java.sql.PreparedStatement) RowSelection(org.hibernate.engine.spi.RowSelection)

Example 3 with ParameterSpecification

use of org.hibernate.param.ParameterSpecification in project hibernate-orm by hibernate.

the class AbstractInlineIdsUpdateHandlerImpl method execute.

@Override
public int execute(SharedSessionContractImplementor session, QueryParameters queryParameters) {
    IdsClauseBuilder values = prepareInlineStatement(session, queryParameters);
    if (!values.getIds().isEmpty()) {
        String[] tableNames = getTargetedQueryable().getConstraintOrderedTableNameClosure();
        String[][] columnNames = getTargetedQueryable().getContraintOrderedTableKeyColumnClosure();
        String idSubselect = values.toStatement();
        assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][];
        for (int tableIndex = 0; tableIndex < tableNames.length; tableIndex++) {
            boolean affected = false;
            final List<ParameterSpecification> parameterList = new ArrayList<>();
            Update update = generateUpdate(tableNames[tableIndex], columnNames[tableIndex], idSubselect, "bulk update");
            final List<AssignmentSpecification> assignmentSpecifications = walker().getAssignmentSpecifications();
            for (AssignmentSpecification assignmentSpecification : assignmentSpecifications) {
                if (assignmentSpecification.affectsTable(tableNames[tableIndex])) {
                    affected = true;
                    update.appendAssignmentFragment(assignmentSpecification.getSqlAssignmentFragment());
                    if (assignmentSpecification.getParameters() != null) {
                        Collections.addAll(parameterList, assignmentSpecification.getParameters());
                    }
                }
            }
            if (affected) {
                updates.put(tableIndex, update.toStatementString());
                assignmentParameterSpecifications[tableIndex] = parameterList.toArray(new ParameterSpecification[parameterList.size()]);
            }
        }
        // Start performing the updates
        for (Map.Entry<Integer, String> updateEntry : updates.entrySet()) {
            int i = updateEntry.getKey();
            String update = updateEntry.getValue();
            if (update == null) {
                continue;
            }
            try {
                try (PreparedStatement ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement(update, false)) {
                    // jdbc params are 1-based
                    int position = 1;
                    if (assignmentParameterSpecifications[i] != null) {
                        for (int x = 0; x < assignmentParameterSpecifications[i].length; x++) {
                            position += assignmentParameterSpecifications[i][x].bind(ps, queryParameters, session, position);
                        }
                    }
                    session.getJdbcCoordinator().getResultSetReturn().executeUpdate(ps);
                }
            } catch (SQLException e) {
                throw convert(e, "error performing bulk update", update);
            }
        }
    }
    return values.getIds().size();
}
Also used : ParameterSpecification(org.hibernate.param.ParameterSpecification) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) Update(org.hibernate.sql.Update) AssignmentSpecification(org.hibernate.hql.internal.ast.tree.AssignmentSpecification) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 4 with ParameterSpecification

use of org.hibernate.param.ParameterSpecification in project hibernate-orm by hibernate.

the class QueryLoader method bindParameterValues.

/**
	 * We specifically override this method here, because in general we know much more
	 * about the parameters and their appropriate bind positions here then we do in
	 * our super because we track them explicitly here through the ParameterSpecification
	 * interface.
	 *
	 * @param queryParameters The encapsulation of the parameter values to be bound.
	 * @param startIndex The position from which to start binding parameter values.
	 * @param session The originating session.
	 *
	 * @return The number of JDBC bind positions actually bound during this method execution.
	 *
	 * @throws SQLException Indicates problems performing the binding.
	 */
@Override
protected int bindParameterValues(final PreparedStatement statement, final QueryParameters queryParameters, final int startIndex, final SharedSessionContractImplementor session) throws SQLException {
    int position = startIndex;
    List<ParameterSpecification> parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
    for (ParameterSpecification spec : parameterSpecs) {
        position += spec.bind(statement, queryParameters, session, position);
    }
    return position - startIndex;
}
Also used : ParameterSpecification(org.hibernate.param.ParameterSpecification)

Example 5 with ParameterSpecification

use of org.hibernate.param.ParameterSpecification in project hibernate-orm by hibernate.

the class AbstractIdsBulkIdHandler method selectIds.

protected List<Object[]> selectIds(SharedSessionContractImplementor session, QueryParameters queryParameters) {
    List<Object[]> ids = new ArrayList<>();
    try {
        try (PreparedStatement ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement(idSelect, false)) {
            int position = 1;
            for (ParameterSpecification parameterSpecification : idSelectParameterSpecifications) {
                position += parameterSpecification.bind(ps, queryParameters, session, position);
            }
            ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract(ps);
            while (rs.next()) {
                Object[] result = new Object[targetedPersister.getIdentifierColumnNames().length];
                for (String columnName : targetedPersister.getIdentifierColumnNames()) {
                    Object column = rs.getObject(columnName);
                    result[rs.findColumn(columnName) - 1] = column;
                }
                ids.add(result);
            }
        }
    } catch (SQLException e) {
        throw convert(e, "could not select ids for bulk operation", idSelect);
    }
    return ids;
}
Also used : ParameterSpecification(org.hibernate.param.ParameterSpecification) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement)

Aggregations

ParameterSpecification (org.hibernate.param.ParameterSpecification)12 PreparedStatement (java.sql.PreparedStatement)5 SQLException (java.sql.SQLException)5 AST (antlr.collections.AST)4 ArrayList (java.util.ArrayList)3 RecognitionException (antlr.RecognitionException)2 SemanticException (antlr.SemanticException)2 QueryException (org.hibernate.QueryException)2 SqlGenerator (org.hibernate.hql.internal.ast.SqlGenerator)2 ParameterNode (org.hibernate.hql.internal.ast.tree.ParameterNode)2 CollectionFilterKeyParameterSpecification (org.hibernate.param.CollectionFilterKeyParameterSpecification)2 NamedParameterSpecification (org.hibernate.param.NamedParameterSpecification)2 PositionalParameterSpecification (org.hibernate.param.PositionalParameterSpecification)2 VersionTypeSeedParameterSpecification (org.hibernate.param.VersionTypeSeedParameterSpecification)2 Queryable (org.hibernate.persister.entity.Queryable)2 VersionType (org.hibernate.type.VersionType)2 UserVersionType (org.hibernate.usertype.UserVersionType)2 ResultSet (java.sql.ResultSet)1 Iterator (java.util.Iterator)1 LinkedHashMap (java.util.LinkedHashMap)1