use of org.hibernate.hql.internal.ast.tree.ParameterNode in project hibernate-orm by hibernate.
the class HqlSqlWalker method prepareFromClauseInputTree.
@Override
protected void prepareFromClauseInputTree(AST fromClauseInput) {
if (!isSubQuery()) {
if (isFilter()) {
// Handle collection-filter compilation.
// IMPORTANT NOTE: This is modifying the INPUT (HQL) tree, not the output tree!
QueryableCollection persister = sessionFactoryHelper.getCollectionPersister(collectionFilterRole);
Type collectionElementType = persister.getElementType();
if (!collectionElementType.isEntityType()) {
throw new QueryException("collection of values in filter: this");
}
String collectionElementEntityName = persister.getElementPersister().getEntityName();
ASTFactory inputAstFactory = hqlParser.getASTFactory();
AST fromElement = inputAstFactory.create(HqlTokenTypes.FILTER_ENTITY, collectionElementEntityName);
ASTUtil.createSibling(inputAstFactory, HqlTokenTypes.ALIAS, "this", fromElement);
fromClauseInput.addChild(fromElement);
// Show the modified AST.
LOG.debug("prepareFromClauseInputTree() : Filter - Added 'this' as a from element...");
queryTranslatorImpl.showHqlAst(hqlParser.getAST());
// Create a parameter specification for the collection filter...
final Type collectionFilterKeyType = sessionFactoryHelper.requireQueryableCollection(collectionFilterRole).getKeyType();
final ParameterNode collectionFilterKeyParameter = (ParameterNode) astFactory.create(PARAM, "?");
final CollectionFilterKeyParameterSpecification collectionFilterKeyParameterSpec = new CollectionFilterKeyParameterSpecification(collectionFilterRole, collectionFilterKeyType);
parameterCount++;
collectionFilterKeyParameter.setHqlParameterSpecification(collectionFilterKeyParameterSpec);
parameterSpecs.add(collectionFilterKeyParameterSpec);
}
}
}
use of org.hibernate.hql.internal.ast.tree.ParameterNode 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);
parameterSpecs.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 parameterSpecs 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.hql.internal.ast.tree.ParameterNode in project hibernate-orm by hibernate.
the class HqlSqlWalker method generatePositionalParameter.
@Override
protected AST generatePositionalParameter(AST delimiterNode, AST numberNode) throws SemanticException {
// todo : we check this multiple times
if (getSessionFactoryHelper().isStrictJPAQLComplianceEnabled() && namedParameters != null) {
throw new SemanticException("Cannot mix positional and named parameters: " + queryTranslatorImpl.getQueryString());
}
if (numberNode == null) {
throw new QueryException(String.format(Locale.ROOT, ERROR_LEGACY_ORDINAL_PARAMS_NO_LONGER_SUPPORTED, queryTranslatorImpl.getQueryString()));
}
final String positionString = numberNode.getText();
final int label = Integer.parseInt(positionString);
trackPositionalParameterPositions(label);
final ParameterNode parameter = (ParameterNode) astFactory.create(PARAM, positionString);
parameter.setText("?");
final int queryParamtersPosition = isFilter() ? label : label - 1;
final PositionalParameterSpecification paramSpec = new PositionalParameterSpecification(delimiterNode.getLine(), delimiterNode.getColumn(), label, queryParamtersPosition);
parameter.setHqlParameterSpecification(paramSpec);
parameterSpecs.add(paramSpec);
return parameter;
}
use of org.hibernate.hql.internal.ast.tree.ParameterNode in project hibernate-orm by hibernate.
the class HqlSqlWalker method generateNamedParameter.
@Override
protected AST generateNamedParameter(AST delimiterNode, AST nameNode) throws SemanticException {
if (getSessionFactoryHelper().isStrictJPAQLComplianceEnabled() && positionalParameters != null) {
throw new SemanticException("Cannot mix positional and named parameters: " + queryTranslatorImpl.getQueryString());
}
final String name = nameNode.getText();
trackNamedParameterPositions(name);
// create the node initially with the param name so that it shows
// appropriately in the "original text" attribute
final ParameterNode parameter = (ParameterNode) astFactory.create(NAMED_PARAM, name);
parameter.setText("?");
final NamedParameterSpecification paramSpec = new NamedParameterSpecification(delimiterNode.getLine(), delimiterNode.getColumn(), name);
parameter.setHqlParameterSpecification(paramSpec);
parameterSpecs.add(paramSpec);
return parameter;
}
use of org.hibernate.hql.internal.ast.tree.ParameterNode in project hibernate-orm by hibernate.
the class HqlSqlWalker method prepareVersioned.
@Override
protected void prepareVersioned(AST updateNode, AST versioned) throws SemanticException {
UpdateStatement updateStatement = (UpdateStatement) updateNode;
FromClause fromClause = updateStatement.getFromClause();
if (versioned != null) {
// Make sure that the persister is versioned
Queryable persister = fromClause.getFromElement().getQueryable();
if (!persister.isVersioned()) {
throw new SemanticException("increment option specified for update of non-versioned entity");
}
VersionType versionType = persister.getVersionType();
if (versionType instanceof UserVersionType) {
throw new SemanticException("user-defined version types not supported for increment option");
}
AST eq = getASTFactory().create(HqlSqlTokenTypes.EQ, "=");
AST versionPropertyNode = generateVersionPropertyNode(persister);
eq.setFirstChild(versionPropertyNode);
AST versionIncrementNode = null;
if (isTimestampBasedVersion(versionType)) {
versionIncrementNode = getASTFactory().create(HqlSqlTokenTypes.PARAM, "?");
ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType);
((ParameterNode) versionIncrementNode).setHqlParameterSpecification(paramSpec);
parameterSpecs.add(0, paramSpec);
} else {
// Not possible to simply re-use the versionPropertyNode here as it causes
// OOM errors due to circularity :(
versionIncrementNode = getASTFactory().create(HqlSqlTokenTypes.PLUS, "+");
versionIncrementNode.setFirstChild(generateVersionPropertyNode(persister));
versionIncrementNode.addChild(getASTFactory().create(HqlSqlTokenTypes.IDENT, "1"));
}
eq.addChild(versionIncrementNode);
evaluateAssignment(eq, persister, 0);
AST setClause = updateStatement.getSetClause();
AST currentFirstSetElement = setClause.getFirstChild();
setClause.setFirstChild(eq);
eq.setNextSibling(currentFirstSetElement);
}
}
Aggregations