HHH-16159 Fix some JSON related issues that came up
This commit is contained in:
parent
4a07b5ed1d
commit
839793e543
39
docker_db.sh
39
docker_db.sh
|
@ -1,6 +1,10 @@
|
||||||
#! /bin/bash
|
#! /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)
|
CONTAINER_CLI=$(command -v podman)
|
||||||
HEALTCHECK_PATH="{{.State.Healthcheck.Status}}"
|
HEALTCHECK_PATH="{{.State.Healthcheck.Status}}"
|
||||||
# Only use sudo for podman
|
# Only use sudo for podman
|
||||||
|
@ -9,10 +13,6 @@ if command -v podman > /dev/null; then
|
||||||
else
|
else
|
||||||
PRIVILEGED_CLI=""
|
PRIVILEGED_CLI=""
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
CONTAINER_CLI=$(command -v docker)
|
|
||||||
HEALTCHECK_PATH="{{.State.Health.Status}}"
|
|
||||||
PRIVILEGED_CLI=""
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mysql() {
|
mysql() {
|
||||||
|
@ -489,7 +489,7 @@ oracle_setup() {
|
||||||
echo "Waiting for Oracle to start..."
|
echo "Waiting for Oracle to start..."
|
||||||
sleep 5;
|
sleep 5;
|
||||||
# On WSL, health-checks intervals don't work for Podman, so run them manually
|
# 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
|
$PRIVILEGED_CLI $CONTAINER_CLI healthcheck run oracle > /dev/null
|
||||||
fi
|
fi
|
||||||
HEALTHSTATUS="`$PRIVILEGED_CLI $CONTAINER_CLI inspect -f $HEALTCHECK_PATH oracle`"
|
HEALTHSTATUS="`$PRIVILEGED_CLI $CONTAINER_CLI inspect -f $HEALTCHECK_PATH oracle`"
|
||||||
|
@ -569,7 +569,7 @@ oracle_free_setup() {
|
||||||
echo "Waiting for Oracle Free to start..."
|
echo "Waiting for Oracle Free to start..."
|
||||||
sleep 5;
|
sleep 5;
|
||||||
# On WSL, health-checks intervals don't work for Podman, so run them manually
|
# 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
|
$PRIVILEGED_CLI $CONTAINER_CLI healthcheck run oracle > /dev/null
|
||||||
fi
|
fi
|
||||||
HEALTHSTATUS="`$PRIVILEGED_CLI $CONTAINER_CLI inspect -f $HEALTCHECK_PATH oracle`"
|
HEALTHSTATUS="`$PRIVILEGED_CLI $CONTAINER_CLI inspect -f $HEALTCHECK_PATH oracle`"
|
||||||
|
@ -658,9 +658,13 @@ disable_userland_proxy() {
|
||||||
echo "Stopping docker..."
|
echo "Stopping docker..."
|
||||||
sudo service docker stop
|
sudo service docker stop
|
||||||
echo "Updating /etc/docker/daemon.json..."
|
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..."
|
echo "Starting docker..."
|
||||||
sudo service docker start
|
sudo service docker start
|
||||||
|
echo "Service status:"
|
||||||
|
sudo journalctl -xeu docker.service
|
||||||
echo "Docker successfully started with userland proxies disabled"
|
echo "Docker successfully started with userland proxies disabled"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -733,6 +737,21 @@ oracle() {
|
||||||
oracle_23
|
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() {
|
oracle_21() {
|
||||||
$PRIVILEGED_CLI $CONTAINER_CLI rm -f oracle || true
|
$PRIVILEGED_CLI $CONTAINER_CLI rm -f oracle || true
|
||||||
disable_userland_proxy
|
disable_userland_proxy
|
||||||
|
@ -765,7 +784,7 @@ oracle_23() {
|
||||||
hana() {
|
hana() {
|
||||||
temp_dir=$(mktemp -d)
|
temp_dir=$(mktemp -d)
|
||||||
echo '{"master_password" : "H1bernate_test"}' >$temp_dir/password.json
|
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 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 \
|
$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 \
|
--memory=8g \
|
||||||
|
@ -775,7 +794,7 @@ hana() {
|
||||||
--sysctl kernel.shmmni=4096 \
|
--sysctl kernel.shmmni=4096 \
|
||||||
--sysctl kernel.shmall=8388608 \
|
--sysctl kernel.shmall=8388608 \
|
||||||
-v $temp_dir:/config:Z \
|
-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 \
|
--passwords-url file:///config/password.json \
|
||||||
--agree-to-sap-license
|
--agree-to-sap-license
|
||||||
# Give the container some time to start
|
# Give the container some time to start
|
||||||
|
|
|
@ -29,6 +29,8 @@ import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
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.BasicPluralType;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.SqlTypes;
|
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,
|
// 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,
|
// 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
|
// 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 );
|
sb.append( customWriteExpressionEnd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.expression.Literal;
|
||||||
import org.hibernate.sql.ast.tree.from.FunctionTableGroup;
|
import org.hibernate.sql.ast.tree.from.FunctionTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
@ -232,6 +232,6 @@ public class H2GenerateSeriesFunction extends NumberSeriesGenerateSeriesFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean needsEmulation(Expression expression) {
|
private static boolean needsEmulation(Expression expression) {
|
||||||
return !( expression instanceof Literal || expression instanceof JdbcParameter);
|
return !( expression instanceof Literal || AbstractSqlAstTranslator.isParameter( expression ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.JsonExistsErrorBehavior;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
|
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
@ -61,7 +61,7 @@ public class CockroachDBJsonExistsFunction extends JsonExistsFunction {
|
||||||
boolean isJsonType,
|
boolean isJsonType,
|
||||||
@Nullable JsonPathPassingClause jsonPathPassingClause,
|
@Nullable JsonPathPassingClause jsonPathPassingClause,
|
||||||
SqlAstTranslator<?> walker) {
|
SqlAstTranslator<?> walker) {
|
||||||
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.JsonPathPassingClause;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonQueryErrorBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonQueryErrorBehavior;
|
||||||
|
@ -76,7 +76,7 @@ public class CockroachDBJsonQueryFunction extends JsonQueryFunction {
|
||||||
boolean isJsonType,
|
boolean isJsonType,
|
||||||
@Nullable JsonPathPassingClause jsonPathPassingClause,
|
@Nullable JsonPathPassingClause jsonPathPassingClause,
|
||||||
SqlAstTranslator<?> walker) {
|
SqlAstTranslator<?> walker) {
|
||||||
final boolean needsCast = !isJsonType && jsonDocumentExpression instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocumentExpression );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,7 +34,7 @@ public class CockroachDBJsonRemoveFunction extends AbstractJsonRemoveFunction {
|
||||||
final Expression json = (Expression) arguments.get( 0 );
|
final Expression json = (Expression) arguments.get( 0 );
|
||||||
final Expression jsonPath = (Expression) arguments.get( 1 );
|
final Expression jsonPath = (Expression) arguments.get( 1 );
|
||||||
sqlAppender.appendSql( "json_remove_path(" );
|
sqlAppender.appendSql( "json_remove_path(" );
|
||||||
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.expression.CastTarget;
|
import org.hibernate.sql.ast.tree.expression.CastTarget;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.JsonPathPassingClause;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonValueEmptyBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonValueEmptyBehavior;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonValueErrorBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonValueErrorBehavior;
|
||||||
|
@ -63,7 +63,7 @@ public class CockroachDBJsonValueFunction extends JsonValueFunction {
|
||||||
if ( castTarget != null ) {
|
if ( castTarget != null ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
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.sql.ast.tree.select.QuerySpec;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
|
@ -153,12 +154,31 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
final TableGroup parentTableGroup = querySpec.getFromClause().queryTableGroups(
|
final TableGroup parentTableGroup = querySpec.getFromClause().queryTableGroups(
|
||||||
tg -> tg.findTableGroupJoin( functionTableGroup ) == null ? null : tg
|
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()
|
final BasicType<Integer> integerType = converter.getCreationContext()
|
||||||
.getSessionFactory()
|
.getSessionFactory()
|
||||||
.getNodeBuilder()
|
.getNodeBuilder()
|
||||||
.getIntegerType();
|
.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(
|
final Expression rhs = new ColumnReference(
|
||||||
functionTableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
functionTableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
||||||
// The default column name for the system_range function
|
// The default column name for the system_range function
|
||||||
|
@ -167,7 +187,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
null,
|
null,
|
||||||
integerType
|
integerType
|
||||||
);
|
);
|
||||||
join.applyPredicate(
|
predicateContainer.applyPredicate(
|
||||||
new ComparisonPredicate( lhs, ComparisonOperator.GREATER_THAN_OR_EQUAL, rhs ) );
|
new ComparisonPredicate( lhs, ComparisonOperator.GREATER_THAN_OR_EQUAL, rhs ) );
|
||||||
}
|
}
|
||||||
final int lastArrayIndex = getLastArrayIndex( arguments.columnsClause(), 0 );
|
final int lastArrayIndex = getLastArrayIndex( arguments.columnsClause(), 0 );
|
||||||
|
@ -176,6 +196,19 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
// for every nested path for arrays
|
// for every nested path for arrays
|
||||||
final String tableIdentifierVariable = functionTableGroup.getPrimaryTableReference()
|
final String tableIdentifierVariable = functionTableGroup.getPrimaryTableReference()
|
||||||
.getIdentificationVariable();
|
.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(
|
final TableGroup tableGroup = new FunctionTableGroup(
|
||||||
functionTableGroup.getNavigablePath().append( "{synthetic}" ),
|
functionTableGroup.getNavigablePath().append( "{synthetic}" ),
|
||||||
null,
|
null,
|
||||||
|
@ -184,6 +217,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
new NestedPathFunctionRenderer(
|
new NestedPathFunctionRenderer(
|
||||||
tableIdentifierVariable,
|
tableIdentifierVariable,
|
||||||
arguments,
|
arguments,
|
||||||
|
jsonDocument,
|
||||||
maximumArraySize,
|
maximumArraySize,
|
||||||
lastArrayIndex
|
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.
|
// 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
|
// Since a table function expression can't render its own `on` clause, this split of logic is necessary
|
||||||
final Expression lhs = new ArrayLengthExpression(
|
final Expression lhs = new ArrayLengthExpression(
|
||||||
determineLastArrayExpression( tableIdentifierVariable, arguments ),
|
determineLastArrayExpression( tableIdentifierVariable, arguments, jsonDocument ),
|
||||||
integerType
|
integerType
|
||||||
);
|
);
|
||||||
final Expression rhs = new ColumnReference(
|
final Expression rhs = new ColumnReference(
|
||||||
|
@ -226,10 +260,10 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
return querySpec;
|
return querySpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Expression determineLastArrayExpression(String tableIdentifierVariable, JsonTableArguments arguments) {
|
private static Expression determineLastArrayExpression(String tableIdentifierVariable, JsonTableArguments arguments, Expression jsonDocument) {
|
||||||
final ArrayExpressionEntry arrayExpressionEntry = determineLastArrayExpression(
|
final ArrayExpressionEntry arrayExpressionEntry = determineLastArrayExpression(
|
||||||
tableIdentifierVariable,
|
tableIdentifierVariable,
|
||||||
determineJsonElement( tableIdentifierVariable, arguments ),
|
determineJsonElement( tableIdentifierVariable, arguments, jsonDocument ),
|
||||||
arguments.columnsClause(),
|
arguments.columnsClause(),
|
||||||
new ArrayExpressionEntry( 0, null )
|
new ArrayExpressionEntry( 0, null )
|
||||||
);
|
);
|
||||||
|
@ -253,7 +287,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
final ArrayExpressionEntry nextArrayExpression;
|
final ArrayExpressionEntry nextArrayExpression;
|
||||||
if ( isArray ) {
|
if ( isArray ) {
|
||||||
final int nextArrayIndex = currentArrayEntry.arrayIndex() + 1;
|
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 );
|
nextArrayExpression = new ArrayExpressionEntry( nextArrayIndex, jsonQueryResult );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -271,10 +305,9 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
return currentArrayEntry;
|
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
|
// Applies the json path and array index access to obtain the "current" processing element
|
||||||
|
|
||||||
final Expression jsonDocument = arguments.jsonDocument();
|
|
||||||
final boolean isArray;
|
final boolean isArray;
|
||||||
final Expression jsonQueryResult;
|
final Expression jsonQueryResult;
|
||||||
if ( arguments.jsonPath() != null ) {
|
if ( arguments.jsonPath() != null ) {
|
||||||
|
@ -309,19 +342,21 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
private static class NestedPathFunctionRenderer implements FunctionRenderer {
|
private static class NestedPathFunctionRenderer implements FunctionRenderer {
|
||||||
private final String tableIdentifierVariable;
|
private final String tableIdentifierVariable;
|
||||||
private final JsonTableArguments arguments;
|
private final JsonTableArguments arguments;
|
||||||
|
private final Expression jsonDocument;
|
||||||
private final int maximumArraySize;
|
private final int maximumArraySize;
|
||||||
private final int lastArrayIndex;
|
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.tableIdentifierVariable = tableIdentifierVariable;
|
||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
|
this.jsonDocument = jsonDocument;
|
||||||
this.maximumArraySize = maximumArraySize;
|
this.maximumArraySize = maximumArraySize;
|
||||||
this.lastArrayIndex = lastArrayIndex;
|
this.lastArrayIndex = lastArrayIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, ReturnableType<?> returnType, SqlAstTranslator<?> walker) {
|
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 );
|
renderNestedColumnJoins( sqlAppender, tableIdentifierVariable, jsonElement, arguments.columnsClause(), 0, lastArrayIndex, walker );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,17 +387,15 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
sqlAppender.appendSql( nextArrayIndex );
|
sqlAppender.appendSql( nextArrayIndex );
|
||||||
sqlAppender.appendSql( '_' );
|
sqlAppender.appendSql( '_' );
|
||||||
|
|
||||||
|
final String ordinalityExpression = ordinalityExpression( tableIdentifierVariable, nextArrayIndex );
|
||||||
// The join condition for the last array will be rendered via TableGroupJoin
|
// The join condition for the last array will be rendered via TableGroupJoin
|
||||||
if ( nextArrayIndex != lastArrayIndex ) {
|
if ( nextArrayIndex != lastArrayIndex ) {
|
||||||
sqlAppender.appendSql( " on coalesce(array_length(" );
|
sqlAppender.appendSql( " on coalesce(array_length(" );
|
||||||
jsonQueryResult.accept( walker );
|
jsonQueryResult.accept( walker );
|
||||||
sqlAppender.append( "),0)>=" );
|
sqlAppender.append( "),0)>=" );
|
||||||
sqlAppender.appendSql( tableIdentifierVariable );
|
sqlAppender.appendSql( ordinalityExpression );
|
||||||
sqlAppender.appendSql( '_' );
|
|
||||||
sqlAppender.appendSql( nextArrayIndex );
|
|
||||||
sqlAppender.appendSql( "_.x" );
|
|
||||||
}
|
}
|
||||||
jsonElement = new ArrayAccessExpression( jsonQueryResult, tableIdentifierVariable + "_" + nextArrayIndex + "_.x" );
|
jsonElement = new ArrayAccessExpression( jsonQueryResult, ordinalityExpression );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jsonElement = jsonQueryResult;
|
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
|
@Override
|
||||||
protected void renderJsonTable(
|
protected void renderJsonTable(
|
||||||
SqlAppender sqlAppender,
|
SqlAppender sqlAppender,
|
||||||
|
@ -397,6 +436,9 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
final Expression jsonPathExpression = arguments.jsonPath();
|
final Expression jsonPathExpression = arguments.jsonPath();
|
||||||
final boolean isArray = isArrayAccess( jsonPathExpression, walker );
|
final boolean isArray = isArrayAccess( jsonPathExpression, walker );
|
||||||
|
|
||||||
|
if ( arguments.jsonDocument().getColumnReference() == null ) {
|
||||||
|
sqlAppender.append( '(' );
|
||||||
|
}
|
||||||
if ( isArray ) {
|
if ( isArray ) {
|
||||||
sqlAppender.append( "system_range(1," );
|
sqlAppender.append( "system_range(1," );
|
||||||
sqlAppender.append( Integer.toString( maximumArraySize ) );
|
sqlAppender.append( Integer.toString( maximumArraySize ) );
|
||||||
|
@ -405,6 +447,17 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
else {
|
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)" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isArrayAccess(@Nullable Expression jsonPath, SqlAstTranslator<?> walker) {
|
private static boolean isArrayAccess(@Nullable Expression jsonPath, SqlAstTranslator<?> walker) {
|
||||||
|
@ -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
|
* 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.
|
* 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,
|
boolean withOrdinality,
|
||||||
SqmToSqlAstConverter converter) {
|
SqmToSqlAstConverter converter) {
|
||||||
final JsonTableArguments arguments = JsonTableArguments.extract( sqlAstNodes );
|
final JsonTableArguments arguments = JsonTableArguments.extract( sqlAstNodes );
|
||||||
final ColumnReference columnReference = arguments.jsonDocument().getColumnReference();
|
final Expression jsonDocument = arguments.jsonDocument();
|
||||||
assert columnReference != null;
|
final String documentPath;
|
||||||
|
final ColumnReference columnReference = jsonDocument.getColumnReference();
|
||||||
final String documentPath = columnReference.getExpressionText();
|
if ( columnReference != null ) {
|
||||||
|
documentPath = columnReference.getExpressionText();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
documentPath = tableIdentifierVariable + "_." + "d";
|
||||||
|
}
|
||||||
|
|
||||||
final String parentPath;
|
final String parentPath;
|
||||||
final boolean isArray;
|
final boolean isArray;
|
||||||
|
@ -620,7 +685,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
final String readExpression;
|
final String readExpression;
|
||||||
if ( isArray ) {
|
if ( isArray ) {
|
||||||
nextClauseLevel = clauseLevel + 1;
|
nextClauseLevel = clauseLevel + 1;
|
||||||
readExpression = "array_get(" + parentPath + "," + tableIdentifierVariable + "_" + nextClauseLevel + "_.x)";
|
readExpression = "array_get(" + parentPath + "," + ordinalityExpression( tableIdentifierVariable, nextClauseLevel ) + ")";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nextClauseLevel = clauseLevel;
|
nextClauseLevel = clauseLevel;
|
||||||
|
@ -633,7 +698,7 @@ public class H2JsonTableFunction extends JsonTableFunction {
|
||||||
addSelectableMapping(
|
addSelectableMapping(
|
||||||
selectableMappings,
|
selectableMappings,
|
||||||
definition.name(),
|
definition.name(),
|
||||||
tableIdentifierVariable + "_" + clauseLevel + "_.x",
|
ordinalityExpression( tableIdentifierVariable, clauseLevel ),
|
||||||
converter.getCreationContext().getTypeConfiguration().getBasicTypeForJavaType( Long.class )
|
converter.getCreationContext().getTypeConfiguration().getBasicTypeForJavaType( Long.class )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.JsonPathPassingClause;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonQueryErrorBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonQueryErrorBehavior;
|
||||||
|
@ -65,7 +65,7 @@ public class PostgreSQLJsonQueryFunction extends JsonQueryFunction {
|
||||||
else {
|
else {
|
||||||
sqlAppender.appendSql( "(select t.v from jsonb_path_query(" );
|
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 ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +33,7 @@ public class PostgreSQLJsonRemoveFunction extends AbstractJsonRemoveFunction {
|
||||||
SqlAstTranslator<?> translator) {
|
SqlAstTranslator<?> translator) {
|
||||||
final Expression json = (Expression) arguments.get( 0 );
|
final Expression json = (Expression) arguments.get( 0 );
|
||||||
final Expression jsonPath = (Expression) arguments.get( 1 );
|
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 ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.expression.Literal;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class PostgreSQLJsonReplaceFunction extends AbstractJsonReplaceFunction {
|
||||||
final Expression jsonPath = (Expression) arguments.get( 1 );
|
final Expression jsonPath = (Expression) arguments.get( 1 );
|
||||||
final SqlAstNode value = arguments.get( 2 );
|
final SqlAstNode value = arguments.get( 2 );
|
||||||
sqlAppender.appendSql( "jsonb_set(" );
|
sqlAppender.appendSql( "jsonb_set(" );
|
||||||
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.expression.Literal;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class PostgreSQLJsonSetFunction extends AbstractJsonSetFunction {
|
||||||
final Expression jsonPath = (Expression) arguments.get( 1 );
|
final Expression jsonPath = (Expression) arguments.get( 1 );
|
||||||
final SqlAstNode value = arguments.get( 2 );
|
final SqlAstNode value = arguments.get( 2 );
|
||||||
sqlAppender.appendSql( "jsonb_set(" );
|
sqlAppender.appendSql( "jsonb_set(" );
|
||||||
final boolean needsCast = !isJsonType( json ) && json instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType( json ) && AbstractSqlAstTranslator.isParameter( json );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||||
import org.hibernate.query.derived.AnonymousTupleTableGroupProducer;
|
import org.hibernate.query.derived.AnonymousTupleTableGroupProducer;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.JsonExistsErrorBehavior;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
|
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonQueryEmptyBehavior;
|
||||||
|
@ -59,7 +59,7 @@ public class PostgreSQLJsonTableFunction extends JsonTableFunction {
|
||||||
|
|
||||||
sqlAppender.appendSql( " from jsonb_path_query(" );
|
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 ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.query.ReturnableType;
|
import org.hibernate.query.ReturnableType;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
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.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.CastTarget;
|
import org.hibernate.sql.ast.tree.expression.CastTarget;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
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.JsonPathPassingClause;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonValueEmptyBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonValueEmptyBehavior;
|
||||||
import org.hibernate.sql.ast.tree.expression.JsonValueErrorBehavior;
|
import org.hibernate.sql.ast.tree.expression.JsonValueErrorBehavior;
|
||||||
|
@ -60,7 +60,7 @@ public class PostgreSQLJsonValueFunction extends JsonValueFunction {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
sqlAppender.appendSql( "jsonb_path_query_first(" );
|
sqlAppender.appendSql( "jsonb_path_query_first(" );
|
||||||
final boolean needsCast = !isJsonType && jsonDocument instanceof JdbcParameter;
|
final boolean needsCast = !isJsonType && AbstractSqlAstTranslator.isParameter( jsonDocument );
|
||||||
if ( needsCast ) {
|
if ( needsCast ) {
|
||||||
sqlAppender.appendSql( "cast(" );
|
sqlAppender.appendSql( "cast(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,22 +43,31 @@ public class SQLServerJsonTableFunction extends JsonTableFunction {
|
||||||
arguments.jsonDocument().accept( walker );
|
arguments.jsonDocument().accept( walker );
|
||||||
if ( arguments.jsonPath() != null ) {
|
if ( arguments.jsonPath() != null ) {
|
||||||
sqlAppender.appendSql( ',' );
|
sqlAppender.appendSql( ',' );
|
||||||
// Default behavior is NULL ON ERROR
|
final String rawJsonPath;
|
||||||
final String prefix = arguments.errorBehavior() == JsonTableErrorBehavior.ERROR ? "strict " : "";
|
|
||||||
final String jsonPathString;
|
|
||||||
if ( arguments.passingClause() != null ) {
|
if ( arguments.passingClause() != null ) {
|
||||||
jsonPathString = prefix + JsonPathHelper.inlinedJsonPathIncludingPassingClause( arguments.jsonPath(),
|
rawJsonPath = JsonPathHelper.inlinedJsonPathIncludingPassingClause(
|
||||||
arguments.passingClause(), walker );
|
arguments.jsonPath(),
|
||||||
|
arguments.passingClause(),
|
||||||
|
walker
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jsonPathString = prefix + walker.getLiteralValue( arguments.jsonPath() );
|
rawJsonPath = walker.getLiteralValue( arguments.jsonPath() );
|
||||||
}
|
}
|
||||||
if ( jsonPathString.endsWith( "[*]" ) ) {
|
final String jsonPath;
|
||||||
sqlAppender.appendSingleQuoteEscapedString( jsonPathString.substring( 0, jsonPathString.length() - 3 ) );
|
if ( arguments.errorBehavior() == JsonTableErrorBehavior.ERROR ) {
|
||||||
|
// Default behavior is NULL ON ERROR
|
||||||
|
jsonPath = "strict " + rawJsonPath;
|
||||||
}
|
}
|
||||||
else {
|
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 ) {
|
else if ( arguments.errorBehavior() == JsonTableErrorBehavior.ERROR ) {
|
||||||
// Default behavior is NULL ON ERROR
|
// Default behavior is NULL ON ERROR
|
||||||
|
|
Loading…
Reference in New Issue