HHH-16159 Fix some JSON related issues that came up

This commit is contained in:
Christian Beikov 2024-11-07 16:52:25 +01:00
parent 4a07b5ed1d
commit 839793e543
15 changed files with 168 additions and 66 deletions

View File

@ -1,6 +1,10 @@
#! /bin/bash
if command -v podman > /dev/null; then
if command -v docker > /dev/null; then
CONTAINER_CLI=$(command -v docker)
HEALTCHECK_PATH="{{.State.Health.Status}}"
PRIVILEGED_CLI=""
else
CONTAINER_CLI=$(command -v podman)
HEALTCHECK_PATH="{{.State.Healthcheck.Status}}"
# Only use sudo for podman
@ -9,10 +13,6 @@ if command -v podman > /dev/null; then
else
PRIVILEGED_CLI=""
fi
else
CONTAINER_CLI=$(command -v docker)
HEALTCHECK_PATH="{{.State.Health.Status}}"
PRIVILEGED_CLI=""
fi
mysql() {
@ -489,7 +489,7 @@ oracle_setup() {
echo "Waiting for Oracle to start..."
sleep 5;
# On WSL, health-checks intervals don't work for Podman, so run them manually
if command -v podman > /dev/null; then
if ! command -v docker > /dev/null; then
$PRIVILEGED_CLI $CONTAINER_CLI healthcheck run oracle > /dev/null
fi
HEALTHSTATUS="`$PRIVILEGED_CLI $CONTAINER_CLI inspect -f $HEALTCHECK_PATH oracle`"
@ -569,7 +569,7 @@ oracle_free_setup() {
echo "Waiting for Oracle Free to start..."
sleep 5;
# On WSL, health-checks intervals don't work for Podman, so run them manually
if command -v podman > /dev/null; then
if ! command -v docker > /dev/null; then
$PRIVILEGED_CLI $CONTAINER_CLI healthcheck run oracle > /dev/null
fi
HEALTHSTATUS="`$PRIVILEGED_CLI $CONTAINER_CLI inspect -f $HEALTCHECK_PATH oracle`"
@ -658,9 +658,13 @@ disable_userland_proxy() {
echo "Stopping docker..."
sudo service docker stop
echo "Updating /etc/docker/daemon.json..."
sudo bash -c 'echo "${docker_daemon_json/\}/,}\"userland-proxy\": false}" > /etc/docker/daemon.json'
sudo bash -c "export docker_daemon_json='$docker_daemon_json'; echo \"\${docker_daemon_json/\}/,}\\\"userland-proxy\\\": false}\" > /etc/docker/daemon.json"
echo "New docker daemon config:"
cat /etc/docker/daemon.json
echo "Starting docker..."
sudo service docker start
echo "Service status:"
sudo journalctl -xeu docker.service
echo "Docker successfully started with userland proxies disabled"
fi
fi
@ -733,6 +737,21 @@ oracle() {
oracle_23
}
oracle_18() {
$PRIVILEGED_CLI $CONTAINER_CLI rm -f oracle || true
disable_userland_proxy
# We need to use the defaults
# SYSTEM/Oracle18
$PRIVILEGED_CLI $CONTAINER_CLI run --name oracle -d -p 1521:1521 -e ORACLE_PASSWORD=Oracle18 \
--cap-add cap_net_raw \
--health-cmd healthcheck.sh \
--health-interval 5s \
--health-timeout 5s \
--health-retries 10 \
${DB_IMAGE_ORACLE_21:-docker.io/gvenzl/oracle-xe:18.4.0}
oracle_setup
}
oracle_21() {
$PRIVILEGED_CLI $CONTAINER_CLI rm -f oracle || true
disable_userland_proxy
@ -765,7 +784,7 @@ oracle_23() {
hana() {
temp_dir=$(mktemp -d)
echo '{"master_password" : "H1bernate_test"}' >$temp_dir/password.json
chmod 777 -R $temp_dir
chmod -R 777 $temp_dir
$PRIVILEGED_CLI $CONTAINER_CLI rm -f hana || true
$PRIVILEGED_CLI $CONTAINER_CLI run -d --name hana -p 39013:39013 -p 39017:39017 -p 39041-39045:39041-39045 -p 1128-1129:1128-1129 -p 59013-59014:59013-59014 \
--memory=8g \
@ -775,7 +794,7 @@ hana() {
--sysctl kernel.shmmni=4096 \
--sysctl kernel.shmall=8388608 \
-v $temp_dir:/config:Z \
${DB_IMAGE_HANA:-docker.io/saplabs/hanaexpress:2.00.072.00.20231123.1} \
${DB_IMAGE_HANA:-docker.io/saplabs/hanaexpress:2.00.076.00.20240701.1} \
--passwords-url file:///config/password.json \
--agree-to-sap-license
# Give the container some time to start

View File

@ -29,6 +29,8 @@ import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.BasicType;
import org.hibernate.type.SqlTypes;
@ -589,7 +591,14 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
// We use NO_UNTYPED here so that expressions which require type inference are casted explicitly,
// since we don't know how the custom write expression looks like where this is embedded,
// so we have to be pessimistic and avoid ambiguities
translator.render( expression.getValueExpression( selectableMapping ), SqlAstNodeRenderingMode.NO_UNTYPED );
final Expression valueExpression = expression.getValueExpression( selectableMapping );
if ( valueExpression instanceof Literal literal && literal.getLiteralValue() == null ) {
// Except for the null literal. That is just rendered as-is
sb.append( "null" );
}
else {
translator.render( valueExpression, SqlAstNodeRenderingMode.NO_UNTYPED );
}
sb.append( customWriteExpressionEnd );
}
}

View File

@ -19,11 +19,11 @@ import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.sql.ast.tree.from.FunctionTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup;
@ -232,6 +232,6 @@ public class H2GenerateSeriesFunction extends NumberSeriesGenerateSeriesFunction
}
private static boolean needsEmulation(Expression expression) {
return !( expression instanceof Literal || expression instanceof JdbcParameter);
return !( expression instanceof Literal || AbstractSqlAstTranslator.isParameter( expression ) );
}
}

View File

@ -11,9 +11,9 @@ import org.hibernate.QueryException;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.JsonExistsErrorBehavior;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
import org.hibernate.type.spi.TypeConfiguration;
@ -61,7 +61,7 @@ public class CockroachDBJsonExistsFunction extends JsonExistsFunction {
boolean isJsonType,
@Nullable JsonPathPassingClause jsonPathPassingClause,
SqlAstTranslator<?> walker) {
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -11,9 +11,9 @@ import org.hibernate.QueryException;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
import org.hibernate.sql.ast.tree.expression.JsonQueryErrorBehavior;
@ -76,7 +76,7 @@ public class CockroachDBJsonQueryFunction extends JsonQueryFunction {
boolean isJsonType,
@Nullable JsonPathPassingClause jsonPathPassingClause,
SqlAstTranslator<?> walker) {
final boolean needsCast = !isJsonType && jsonDocumentExpression instanceof JdbcParameter;
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocumentExpression );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -10,10 +10,10 @@ import org.hibernate.QueryException;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -34,7 +34,7 @@ public class CockroachDBJsonRemoveFunction extends AbstractJsonRemoveFunction {
final Expression json = (Expression) arguments.get( 0 );
final Expression jsonPath = (Expression) arguments.get( 1 );
sqlAppender.appendSql( "json_remove_path(" );
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -10,10 +10,10 @@ import org.hibernate.QueryException;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
import org.hibernate.sql.ast.tree.expression.JsonValueEmptyBehavior;
import org.hibernate.sql.ast.tree.expression.JsonValueErrorBehavior;
@ -63,7 +63,7 @@ public class CockroachDBJsonValueFunction extends JsonValueFunction {
if ( castTarget != null ) {
sqlAppender.appendSql( "cast(" );
}
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -53,6 +53,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.predicate.PredicateContainer;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.type.BasicType;
import org.hibernate.type.SqlTypes;
@ -153,12 +154,31 @@ public class H2JsonTableFunction extends JsonTableFunction {
final TableGroup parentTableGroup = querySpec.getFromClause().queryTableGroups(
tg -> tg.findTableGroupJoin( functionTableGroup ) == null ? null : tg
);
final TableGroupJoin join = parentTableGroup.findTableGroupJoin( functionTableGroup );
final PredicateContainer predicateContainer;
if ( parentTableGroup != null ) {
predicateContainer = parentTableGroup.findTableGroupJoin( functionTableGroup );
}
else {
predicateContainer = querySpec;
}
final BasicType<Integer> integerType = converter.getCreationContext()
.getSessionFactory()
.getNodeBuilder()
.getIntegerType();
final Expression lhs = new ArrayLengthExpression( arguments.jsonDocument(), integerType );
final Expression jsonDocument;
if ( arguments.jsonDocument().getColumnReference() == null ) {
jsonDocument = new ColumnReference(
functionTableGroup.getPrimaryTableReference().getIdentificationVariable() + "_",
"d",
false,
null,
arguments.jsonDocument().getExpressionType().getSingleJdbcMapping()
);
}
else {
jsonDocument = arguments.jsonDocument();
}
final Expression lhs = new ArrayLengthExpression( jsonDocument, integerType );
final Expression rhs = new ColumnReference(
functionTableGroup.getPrimaryTableReference().getIdentificationVariable(),
// The default column name for the system_range function
@ -167,7 +187,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
null,
integerType
);
join.applyPredicate(
predicateContainer.applyPredicate(
new ComparisonPredicate( lhs, ComparisonOperator.GREATER_THAN_OR_EQUAL, rhs ) );
}
final int lastArrayIndex = getLastArrayIndex( arguments.columnsClause(), 0 );
@ -176,6 +196,19 @@ public class H2JsonTableFunction extends JsonTableFunction {
// for every nested path for arrays
final String tableIdentifierVariable = functionTableGroup.getPrimaryTableReference()
.getIdentificationVariable();
final Expression jsonDocument;
if ( arguments.jsonDocument().getColumnReference() == null ) {
jsonDocument = new ColumnReference(
tableIdentifierVariable + "_",
"d",
false,
null,
arguments.jsonDocument().getExpressionType().getSingleJdbcMapping()
);
}
else {
jsonDocument = arguments.jsonDocument();
}
final TableGroup tableGroup = new FunctionTableGroup(
functionTableGroup.getNavigablePath().append( "{synthetic}" ),
null,
@ -184,6 +217,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
new NestedPathFunctionRenderer(
tableIdentifierVariable,
arguments,
jsonDocument,
maximumArraySize,
lastArrayIndex
),
@ -207,7 +241,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
// The join predicate compares the length of the last array expression against system_range() index.
// Since a table function expression can't render its own `on` clause, this split of logic is necessary
final Expression lhs = new ArrayLengthExpression(
determineLastArrayExpression( tableIdentifierVariable, arguments ),
determineLastArrayExpression( tableIdentifierVariable, arguments, jsonDocument ),
integerType
);
final Expression rhs = new ColumnReference(
@ -226,10 +260,10 @@ public class H2JsonTableFunction extends JsonTableFunction {
return querySpec;
}
private static Expression determineLastArrayExpression(String tableIdentifierVariable, JsonTableArguments arguments) {
private static Expression determineLastArrayExpression(String tableIdentifierVariable, JsonTableArguments arguments, Expression jsonDocument) {
final ArrayExpressionEntry arrayExpressionEntry = determineLastArrayExpression(
tableIdentifierVariable,
determineJsonElement( tableIdentifierVariable, arguments ),
determineJsonElement( tableIdentifierVariable, arguments, jsonDocument ),
arguments.columnsClause(),
new ArrayExpressionEntry( 0, null )
);
@ -253,7 +287,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
final ArrayExpressionEntry nextArrayExpression;
if ( isArray ) {
final int nextArrayIndex = currentArrayEntry.arrayIndex() + 1;
jsonElement = new ArrayAccessExpression( jsonQueryResult, tableIdentifierVariable + "_" + nextArrayIndex + "_.x" );
jsonElement = new ArrayAccessExpression( jsonQueryResult, ordinalityExpression( tableIdentifierVariable, nextArrayIndex ) );
nextArrayExpression = new ArrayExpressionEntry( nextArrayIndex, jsonQueryResult );
}
else {
@ -271,10 +305,9 @@ public class H2JsonTableFunction extends JsonTableFunction {
return currentArrayEntry;
}
private static Expression determineJsonElement(String tableIdentifierVariable, JsonTableArguments arguments) {
private static Expression determineJsonElement(String tableIdentifierVariable, JsonTableArguments arguments, Expression jsonDocument) {
// Applies the json path and array index access to obtain the "current" processing element
final Expression jsonDocument = arguments.jsonDocument();
final boolean isArray;
final Expression jsonQueryResult;
if ( arguments.jsonPath() != null ) {
@ -309,19 +342,21 @@ public class H2JsonTableFunction extends JsonTableFunction {
private static class NestedPathFunctionRenderer implements FunctionRenderer {
private final String tableIdentifierVariable;
private final JsonTableArguments arguments;
private final Expression jsonDocument;
private final int maximumArraySize;
private final int lastArrayIndex;
public NestedPathFunctionRenderer(String tableIdentifierVariable, JsonTableArguments arguments, int maximumArraySize, int lastArrayIndex) {
public NestedPathFunctionRenderer(String tableIdentifierVariable, JsonTableArguments arguments, Expression jsonDocument, int maximumArraySize, int lastArrayIndex) {
this.tableIdentifierVariable = tableIdentifierVariable;
this.arguments = arguments;
this.jsonDocument = jsonDocument;
this.maximumArraySize = maximumArraySize;
this.lastArrayIndex = lastArrayIndex;
}
@Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, ReturnableType<?> returnType, SqlAstTranslator<?> walker) {
final Expression jsonElement = determineJsonElement( tableIdentifierVariable, arguments );
final Expression jsonElement = determineJsonElement( tableIdentifierVariable, arguments, jsonDocument );
renderNestedColumnJoins( sqlAppender, tableIdentifierVariable, jsonElement, arguments.columnsClause(), 0, lastArrayIndex, walker );
}
@ -352,17 +387,15 @@ public class H2JsonTableFunction extends JsonTableFunction {
sqlAppender.appendSql( nextArrayIndex );
sqlAppender.appendSql( '_' );
final String ordinalityExpression = ordinalityExpression( tableIdentifierVariable, nextArrayIndex );
// The join condition for the last array will be rendered via TableGroupJoin
if ( nextArrayIndex != lastArrayIndex ) {
sqlAppender.appendSql( " on coalesce(array_length(" );
jsonQueryResult.accept( walker );
sqlAppender.append( "),0)>=" );
sqlAppender.appendSql( tableIdentifierVariable );
sqlAppender.appendSql( '_' );
sqlAppender.appendSql( nextArrayIndex );
sqlAppender.appendSql( "_.x" );
sqlAppender.appendSql( ordinalityExpression );
}
jsonElement = new ArrayAccessExpression( jsonQueryResult, tableIdentifierVariable + "_" + nextArrayIndex + "_.x" );
jsonElement = new ArrayAccessExpression( jsonQueryResult, ordinalityExpression );
}
else {
jsonElement = jsonQueryResult;
@ -383,6 +416,12 @@ public class H2JsonTableFunction extends JsonTableFunction {
}
}
@Override
public boolean rendersIdentifierVariable(List<SqlAstNode> arguments, SessionFactoryImplementor sessionFactory) {
// To make our lives simpler when supporting non-column JSON document arguments
return true;
}
@Override
protected void renderJsonTable(
SqlAppender sqlAppender,
@ -397,13 +436,27 @@ public class H2JsonTableFunction extends JsonTableFunction {
final Expression jsonPathExpression = arguments.jsonPath();
final boolean isArray = isArrayAccess( jsonPathExpression, walker );
if ( arguments.jsonDocument().getColumnReference() == null ) {
sqlAppender.append( '(' );
}
if ( isArray ) {
sqlAppender.append( "system_range(1," );
sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ")" );
sqlAppender.append( ") " );
}
else {
sqlAppender.append( "system_range(1,1)" );
sqlAppender.append( "system_range(1,1) " );
}
sqlAppender.append( tableIdentifierVariable );
if ( arguments.jsonDocument().getColumnReference() == null ) {
sqlAppender.append( " join (values (" );
arguments.jsonDocument().accept( walker );
if ( !arguments.isJsonType() ) {
sqlAppender.append( " format json" );
}
sqlAppender.append( ")) " );
sqlAppender.append( tableIdentifierVariable );
sqlAppender.append( "_(d) on 1=1)" );
}
}
@ -526,6 +579,13 @@ public class H2JsonTableFunction extends JsonTableFunction {
}
}
private static String ordinalityExpression(String tableIdentifierVariable, int clauseLevel) {
if ( clauseLevel == 0 ) {
return tableIdentifierVariable + ".x";
}
return tableIdentifierVariable + "_" + clauseLevel + "_.x";
}
/**
* This type resolver essentially implements all the JSON path handling and casting via column read expressions
* instead of rendering to the {@code from} clause like other {@code json_table()} implementations.
@ -545,10 +605,15 @@ public class H2JsonTableFunction extends JsonTableFunction {
boolean withOrdinality,
SqmToSqlAstConverter converter) {
final JsonTableArguments arguments = JsonTableArguments.extract( sqlAstNodes );
final ColumnReference columnReference = arguments.jsonDocument().getColumnReference();
assert columnReference != null;
final String documentPath = columnReference.getExpressionText();
final Expression jsonDocument = arguments.jsonDocument();
final String documentPath;
final ColumnReference columnReference = jsonDocument.getColumnReference();
if ( columnReference != null ) {
documentPath = columnReference.getExpressionText();
}
else {
documentPath = tableIdentifierVariable + "_." + "d";
}
final String parentPath;
final boolean isArray;
@ -620,7 +685,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
final String readExpression;
if ( isArray ) {
nextClauseLevel = clauseLevel + 1;
readExpression = "array_get(" + parentPath + "," + tableIdentifierVariable + "_" + nextClauseLevel + "_.x)";
readExpression = "array_get(" + parentPath + "," + ordinalityExpression( tableIdentifierVariable, nextClauseLevel ) + ")";
}
else {
nextClauseLevel = clauseLevel;
@ -633,7 +698,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
addSelectableMapping(
selectableMappings,
definition.name(),
tableIdentifierVariable + "_" + clauseLevel + "_.x",
ordinalityExpression( tableIdentifierVariable, clauseLevel ),
converter.getCreationContext().getTypeConfiguration().getBasicTypeForJavaType( Long.class )
);
}

View File

@ -10,10 +10,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.QueryException;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
import org.hibernate.sql.ast.tree.expression.JsonQueryErrorBehavior;
@ -65,7 +65,7 @@ public class PostgreSQLJsonQueryFunction extends JsonQueryFunction {
else {
sqlAppender.appendSql( "(select t.v from jsonb_path_query(" );
}
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -10,10 +10,10 @@ import org.hibernate.QueryException;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -33,7 +33,7 @@ public class PostgreSQLJsonRemoveFunction extends AbstractJsonRemoveFunction {
SqlAstTranslator<?> translator) {
final Expression json = (Expression) arguments.get( 0 );
final Expression jsonPath = (Expression) arguments.get( 1 );
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -10,10 +10,10 @@ import org.hibernate.QueryException;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.type.spi.TypeConfiguration;
@ -36,7 +36,7 @@ public class PostgreSQLJsonReplaceFunction extends AbstractJsonReplaceFunction {
final Expression jsonPath = (Expression) arguments.get( 1 );
final SqlAstNode value = arguments.get( 2 );
sqlAppender.appendSql( "jsonb_set(" );
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -10,10 +10,10 @@ import org.hibernate.QueryException;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.type.spi.TypeConfiguration;
@ -36,7 +36,7 @@ public class PostgreSQLJsonSetFunction extends AbstractJsonSetFunction {
final Expression jsonPath = (Expression) arguments.get( 1 );
final SqlAstNode value = arguments.get( 2 );
sqlAppender.appendSql( "jsonb_set(" );
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -9,10 +9,10 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.derived.AnonymousTupleTableGroupProducer;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.JsonExistsErrorBehavior;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
@ -59,7 +59,7 @@ public class PostgreSQLJsonTableFunction extends JsonTableFunction {
sqlAppender.appendSql( " from jsonb_path_query(" );
final boolean needsCast = !arguments.isJsonType() && arguments.jsonDocument() instanceof JdbcParameter;
final boolean needsCast = !arguments.isJsonType() && AbstractSqlAstTranslator.isParameter( arguments.jsonDocument() );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -10,11 +10,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.QueryException;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
import org.hibernate.sql.ast.tree.expression.JsonValueEmptyBehavior;
import org.hibernate.sql.ast.tree.expression.JsonValueErrorBehavior;
@ -60,7 +60,7 @@ public class PostgreSQLJsonValueFunction extends JsonValueFunction {
sqlAppender.appendSql( "cast(" );
}
sqlAppender.appendSql( "jsonb_path_query_first(" );
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
if ( needsCast ) {
sqlAppender.appendSql( "cast(" );
}

View File

@ -43,22 +43,31 @@ public class SQLServerJsonTableFunction extends JsonTableFunction {
arguments.jsonDocument().accept( walker );
if ( arguments.jsonPath() != null ) {
sqlAppender.appendSql( ',' );
// Default behavior is NULL ON ERROR
final String prefix = arguments.errorBehavior() == JsonTableErrorBehavior.ERROR ? "strict " : "";
final String jsonPathString;
final String rawJsonPath;
if ( arguments.passingClause() != null ) {
jsonPathString = prefix + JsonPathHelper.inlinedJsonPathIncludingPassingClause( arguments.jsonPath(),
arguments.passingClause(), walker );
rawJsonPath = JsonPathHelper.inlinedJsonPathIncludingPassingClause(
arguments.jsonPath(),
arguments.passingClause(),
walker
);
}
else {
jsonPathString = prefix + walker.getLiteralValue( arguments.jsonPath() );
rawJsonPath = walker.getLiteralValue( arguments.jsonPath() );
}
if ( jsonPathString.endsWith( "[*]" ) ) {
sqlAppender.appendSingleQuoteEscapedString( jsonPathString.substring( 0, jsonPathString.length() - 3 ) );
final String jsonPath;
if ( arguments.errorBehavior() == JsonTableErrorBehavior.ERROR ) {
// Default behavior is NULL ON ERROR
jsonPath = "strict " + rawJsonPath;
}
else {
sqlAppender.appendSingleQuoteEscapedString( jsonPathString );
jsonPath = rawJsonPath;
}
sqlAppender.appendSingleQuoteEscapedString(
// openjson unwraps arrays automatically and doesn't support this syntax, so remove it
jsonPath.endsWith( "[*]" )
? jsonPath.substring( 0, jsonPath.length() - 3 )
: jsonPath
);
}
else if ( arguments.errorBehavior() == JsonTableErrorBehavior.ERROR ) {
// Default behavior is NULL ON ERROR