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);
}
}
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);
}
}
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();
}
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;
}
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;
}
Aggregations