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
|
||||
|
||||
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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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(" );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue