Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit 3ce4933

Browse files
feat: add support for parameterMode in QueryJobConfiguration to unblock JDBC migration to the Java client library (#1223)
1 parent 0a271cb commit 3ce4933

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryJobConfiguration.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public final class QueryJobConfiguration extends JobConfiguration {
4747
private final String query;
4848
private final ImmutableList<QueryParameterValue> positionalParameters;
4949
private final ImmutableMap<String, QueryParameterValue> namedParameters;
50+
private final String parameterMode;
5051
private final TableId destinationTable;
5152
private final Map<String, ExternalTableDefinition> tableDefinitions;
5253
private final List<UserDefinedFunction> userDefinedFunctions;
@@ -98,6 +99,7 @@ public static final class Builder
9899
private String query;
99100
private List<QueryParameterValue> positionalParameters = Lists.newArrayList();
100101
private Map<String, QueryParameterValue> namedParameters = Maps.newHashMap();
102+
private String parameterMode;
101103
private TableId destinationTable;
102104
private Map<String, ExternalTableDefinition> tableDefinitions;
103105
private List<UserDefinedFunction> userDefinedFunctions;
@@ -131,6 +133,7 @@ private Builder(QueryJobConfiguration jobConfiguration) {
131133
this.query = jobConfiguration.query;
132134
this.namedParameters = jobConfiguration.namedParameters;
133135
this.positionalParameters = jobConfiguration.positionalParameters;
136+
this.parameterMode = jobConfiguration.parameterMode;
134137
this.destinationTable = jobConfiguration.destinationTable;
135138
this.tableDefinitions = jobConfiguration.tableDefinitions;
136139
this.userDefinedFunctions = jobConfiguration.userDefinedFunctions;
@@ -163,11 +166,13 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur
163166
if (queryConfigurationPb.getQueryParameters() != null
164167
&& !queryConfigurationPb.getQueryParameters().isEmpty()) {
165168
if (queryConfigurationPb.getQueryParameters().get(0).getName() == null) {
169+
parameterMode = "POSITIONAL";
166170
setPositionalParameters(
167171
Lists.transform(
168172
queryConfigurationPb.getQueryParameters(),
169173
POSITIONAL_PARAMETER_FROM_PB_FUNCTION));
170174
} else {
175+
parameterMode = "NAMED";
171176
Map<String, QueryParameterValue> values = Maps.newHashMap();
172177
for (QueryParameter queryParameterPb : queryConfigurationPb.getQueryParameters()) {
173178
checkNotNull(queryParameterPb.getName());
@@ -277,6 +282,16 @@ public Builder addPositionalParameter(QueryParameterValue value) {
277282
return this;
278283
}
279284

285+
/**
286+
* Standard SQL only. Set to POSITIONAL to use positional (?) query parameters or to NAMED to
287+
* use named (@myparam) query parameters in this query.
288+
*/
289+
public Builder setParameterMode(String parameterMode) {
290+
checkNotNull(parameterMode);
291+
this.parameterMode = parameterMode;
292+
return this;
293+
}
294+
280295
/**
281296
* Sets the query parameters to a list of positional query parameters to use in the query.
282297
*
@@ -639,6 +654,7 @@ private QueryJobConfiguration(Builder builder) {
639654
}
640655
positionalParameters = ImmutableList.copyOf(builder.positionalParameters);
641656
namedParameters = ImmutableMap.copyOf(builder.namedParameters);
657+
this.parameterMode = builder.parameterMode;
642658
this.allowLargeResults = builder.allowLargeResults;
643659
this.createDisposition = builder.createDisposition;
644660
this.defaultDataset = builder.defaultDataset;
@@ -876,6 +892,7 @@ ToStringHelper toStringHelper() {
876892
.add("query", query)
877893
.add("positionalParameters", positionalParameters)
878894
.add("namedParameters", namedParameters)
895+
.add("parameterMode", parameterMode)
879896
.add("destinationTable", destinationTable)
880897
.add("destinationEncryptionConfiguration", destinationEncryptionConfiguration)
881898
.add("defaultDataset", defaultDataset)
@@ -919,6 +936,7 @@ public int hashCode() {
919936
query,
920937
positionalParameters,
921938
namedParameters,
939+
parameterMode,
922940
tableDefinitions,
923941
useQueryCache,
924942
userDefinedFunctions,
@@ -963,6 +981,9 @@ com.google.api.services.bigquery.model.JobConfiguration toPb() {
963981
Lists.transform(namedParameters.entrySet().asList(), NAMED_PARAMETER_TO_PB_FUNCTION);
964982
queryConfigurationPb.setQueryParameters(queryParametersPb);
965983
}
984+
if (parameterMode != null) {
985+
queryConfigurationPb.setParameterMode(parameterMode);
986+
}
966987
configurationPb.setDryRun(dryRun());
967988
if (allowLargeResults != null) {
968989
queryConfigurationPb.setAllowLargeResults(allowLargeResults);

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryJobConfigurationTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public class QueryJobConfigurationTest {
108108
ImmutableList.of(STRING_PARAMETER, TIMESTAMP_PARAMETER, BIGNUMERIC_PARAMETER);
109109
private static final Map<String, QueryParameterValue> NAME_PARAMETER =
110110
ImmutableMap.of("string", STRING_PARAMETER, "timestamp", TIMESTAMP_PARAMETER);
111+
private static final String PARAMETER_MODE = "POSITIONAL";
111112
private static final QueryJobConfiguration QUERY_JOB_CONFIGURATION =
112113
QueryJobConfiguration.newBuilder(QUERY)
113114
.setUseQueryCache(USE_QUERY_CACHE)
@@ -133,6 +134,7 @@ public class QueryJobConfigurationTest {
133134
.setRangePartitioning(RANGE_PARTITIONING)
134135
.setConnectionProperties(CONNECTION_PROPERTIES)
135136
.setPositionalParameters(POSITIONAL_PARAMETER)
137+
.setParameterMode(PARAMETER_MODE)
136138
.build();
137139
private static final QueryJobConfiguration QUERY_JOB_CONFIGURATION_ADD_POSITIONAL_PARAMETER =
138140
QUERY_JOB_CONFIGURATION

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,6 +2099,33 @@ public void testScriptStatistics() throws InterruptedException {
20992099
}
21002100
}
21012101

2102+
@Test
2103+
public void testQueryParameterModeWithDryRun() {
2104+
String query =
2105+
"SELECT TimestampField, StringField, BooleanField, BigNumericField, BigNumericField1, BigNumericField2, BigNumericField3, BigNumericField4 FROM "
2106+
+ TABLE_ID.getTable()
2107+
+ " WHERE StringField = ?"
2108+
+ " AND TimestampField > ?"
2109+
+ " AND IntegerField IN UNNEST(?)"
2110+
+ " AND IntegerField < ?"
2111+
+ " AND FloatField > ?"
2112+
+ " AND NumericField < ?"
2113+
+ " AND BigNumericField = ?";
2114+
2115+
QueryJobConfiguration queryConfig =
2116+
QueryJobConfiguration.newBuilder(query)
2117+
.setDefaultDataset(DatasetId.of(DATASET))
2118+
.setParameterMode("POSITIONAL")
2119+
.setUseLegacySql(false)
2120+
.setDryRun(true)
2121+
.build();
2122+
2123+
Job job = bigquery.create(JobInfo.of(queryConfig));
2124+
JobStatistics.QueryStatistics statistics = job.getStatistics();
2125+
2126+
assertNotNull(statistics.getTotalBytesProcessed());
2127+
}
2128+
21022129
@Test
21032130
public void testPositionalQueryParameters() throws InterruptedException {
21042131
String query =

0 commit comments

Comments
 (0)