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

Commit 5a1e647

Browse files
authored
Merge branch 'main' into jdbc/refactor-connection-properties
2 parents f8c57c5 + ecbf402 commit 5a1e647

8 files changed

Lines changed: 105 additions & 31 deletions

File tree

google-cloud-bigquery-jdbc/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@
4848
<version>3.5.2</version>
4949
<configuration>
5050
<skip>${skipSurefire}</skip>
51+
<systemPropertyVariables>
52+
<JDBC_TESTS>true</JDBC_TESTS>
53+
</systemPropertyVariables>
54+
</configuration>
55+
</plugin>
56+
<plugin>
57+
<groupId>org.apache.maven.plugins</groupId>
58+
<artifactId>maven-failsafe-plugin</artifactId>
59+
<configuration>
60+
<systemPropertyVariables>
61+
<JDBC_TESTS>true</JDBC_TESTS>
62+
</systemPropertyVariables>
5163
</configuration>
5264
</plugin>
5365
<plugin>

google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.cloud.bigquery.Job;
3333
import com.google.cloud.bigquery.JobInfo;
3434
import com.google.cloud.bigquery.QueryJobConfiguration;
35+
import com.google.cloud.bigquery.QueryJobConfiguration.JobCreationMode;
3536
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
3637
import com.google.cloud.bigquery.exception.BigQueryJdbcRuntimeException;
3738
import com.google.cloud.bigquery.exception.BigQueryJdbcSqlFeatureNotSupportedException;
@@ -934,8 +935,12 @@ private BigQuery getBigQueryConnection() {
934935
bigQueryOptions.setTransportOptions(this.httpTransportOptions);
935936
}
936937

937-
BigQueryOptions options = bigQueryOptions.setHeaderProvider(this.headerProvider).build();
938-
options.setQueryPreviewEnabled(String.valueOf(this.useStatelessQueryMode));
938+
BigQueryOptions options = bigQueryOptions.setHeaderProvider(HEADER_PROVIDER).build();
939+
options.setDefaultJobCreationMode(
940+
this.useStatelessQueryMode
941+
? JobCreationMode.JOB_CREATION_OPTIONAL
942+
: JobCreationMode.JOB_CREATION_REQUIRED);
943+
939944
return options.getService();
940945
}
941946

google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionProperty.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
package com.google.cloud.bigquery.jdbc;
1818

1919
import java.util.List;
20+
import java.util.function.Supplier;
2021

2122
class BigQueryConnectionProperty {
2223

2324
private final String name;
2425
private final String description;
2526
private final String defaultValue;
27+
private final Supplier<String> defaultValueSupplier;
2628
private final List<String> validValues;
2729

2830
public String getName() {
@@ -34,6 +36,9 @@ public String getDescription() {
3436
}
3537

3638
public String getDefaultValue() {
39+
if (defaultValueSupplier != null) {
40+
return defaultValueSupplier.get();
41+
}
3742
return defaultValue;
3843
}
3944

@@ -43,6 +48,7 @@ public List<String> getValidValues() {
4348

4449
BigQueryConnectionProperty(Builder builder) {
4550
this.name = builder.name;
51+
this.defaultValueSupplier = builder.defaultValueSupplier;
4652
this.defaultValue = builder.defaultValue;
4753
this.description = builder.description;
4854
this.validValues = builder.validValues;
@@ -79,6 +85,7 @@ static final class Builder {
7985
private String name;
8086
private String description;
8187
private String defaultValue;
88+
private Supplier<String> defaultValueSupplier = null;
8289
private List<String> validValues;
8390

8491
private Builder(BigQueryConnectionProperty bigQueryConnectionProperty) {
@@ -105,6 +112,11 @@ Builder setDefaultValue(String defaultValue) {
105112
return this;
106113
}
107114

115+
Builder setLazyDefaultValue(Supplier<String> defaultValueSupplier) {
116+
this.defaultValueSupplier = defaultValueSupplier;
117+
return this;
118+
}
119+
108120
Builder setValidValues(List<String> validValues) {
109121
this.validValues = validValues;
110122
return this;

google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.awt.Desktop;
3939
import java.io.BufferedReader;
4040
import java.io.ByteArrayInputStream;
41+
import java.io.FileInputStream;
4142
import java.io.IOException;
4243
import java.io.InputStream;
4344
import java.io.InputStreamReader;
@@ -299,11 +300,11 @@ private static boolean isFileExists(String filename) {
299300
}
300301
}
301302

302-
private static boolean isJson(String value) {
303+
private static boolean isJson(byte[] value) {
303304
try {
304305
// This is done this way to ensure strict Json parsing
305306
// https://github.com/google/gson/issues/1208#issuecomment-2120764686
306-
InputStream stream = new ByteArrayInputStream(value.getBytes());
307+
InputStream stream = new ByteArrayInputStream(value);
307308
InputStreamReader reader = new InputStreamReader(stream);
308309
JsonReader jsonReader = new JsonReader(reader);
309310
jsonReader.setStrictness(Strictness.STRICT);
@@ -333,17 +334,24 @@ private static GoogleCredentials getGoogleServiceAccountCredentials(
333334

334335
final String keyPath = pvtKeyPath != null ? pvtKeyPath : pvtKey;
335336
PrivateKey key = null;
336-
InputStream stream = null;
337+
byte[] keyBytes = pvtKey != null ? pvtKey.getBytes() : null;
337338

338339
if (isFileExists(keyPath)) {
339-
key = privateKeyFromP12File(keyPath, p12Password);
340-
if (key == null) {
341-
stream = Files.newInputStream(Paths.get(keyPath));
340+
try (InputStream stream = new FileInputStream(keyPath)) {
341+
int bufferSize = 1024 * 1024;
342+
byte[] buffer = new byte[bufferSize];
343+
stream.read(buffer, 0, bufferSize);
344+
keyBytes = buffer;
342345
}
343-
} else if (isJson(pvtKey)) {
344-
stream = new ByteArrayInputStream(pvtKey.getBytes());
346+
}
347+
348+
InputStream stream = null;
349+
if (isJson(keyBytes)) {
350+
stream = new ByteArrayInputStream(keyBytes);
345351
} else if (pvtKey != null) {
346352
key = privateKeyFromPkcs8(pvtKey);
353+
} else if (keyBytes != null) {
354+
key = privateKeyFromP12Bytes(keyBytes, p12Password);
347355
}
348356

349357
if (stream != null) {
@@ -672,9 +680,9 @@ private static GoogleCredentials getServiceAccountImpersonatedCredentials(
672680
impersonationLifetimeInt);
673681
}
674682

675-
static PrivateKey privateKeyFromP12File(String privateKeyFile, String password) {
683+
static PrivateKey privateKeyFromP12Bytes(byte[] privateKey, String password) {
676684
try {
677-
InputStream stream = Files.newInputStream(Paths.get(privateKeyFile));
685+
InputStream stream = new ByteArrayInputStream(privateKey);
678686
return SecurityUtils.loadPrivateKeyFromKeyStore(
679687
SecurityUtils.getPkcs12KeyStore(), stream, "notasecret", "privatekey", password);
680688
} catch (IOException | GeneralSecurityException e) {

google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class BigQueryJdbcRootLogger {
4343
private static final Logger logger = Logger.getLogger("com.google.cloud.bigquery");
4444

4545
private static final Logger storageLogger = Logger.getLogger("com.google.cloud.bigquery.storage");
46+
private static final boolean isTest = Boolean.getBoolean("JDBC_TESTS");
4647

4748
private static Handler fileHandler = null;
4849
private static Path currentLogPath = null;
@@ -51,6 +52,12 @@ class BigQueryJdbcRootLogger {
5152
static {
5253
logger.setUseParentHandlers(false);
5354
storageLogger.setUseParentHandlers(true);
55+
if (isTest) {
56+
ConsoleHandler consoleHandler = new ConsoleHandler();
57+
consoleHandler.setLevel(Level.SEVERE);
58+
consoleHandler.setFormatter(getFormatter());
59+
logger.addHandler(consoleHandler);
60+
}
5461
}
5562

5663
public static Formatter getFormatter() {
@@ -111,13 +118,12 @@ private static void setHandler() throws IOException {
111118
// If File handler exists, use it. Else create new one.
112119
for (Handler h : logger.getHandlers()) {
113120
if (h instanceof ConsoleHandler) {
114-
h.close();
115-
logger.removeHandler(h);
116-
break;
117-
}
118-
if (h instanceof FileHandler) {
121+
if (!isTest) {
122+
h.close();
123+
logger.removeHandler(h);
124+
}
125+
} else if (h instanceof FileHandler) {
119126
fileHandler = h;
120-
break;
121127
}
122128
}
123129

google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcUrlUtility.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.Map.Entry;
3333
import java.util.Properties;
3434
import java.util.Set;
35+
import java.util.function.Supplier;
3536
import java.util.logging.Level;
3637
import java.util.regex.Matcher;
3738
import java.util.regex.Pattern;
@@ -358,7 +359,7 @@ protected boolean removeEldestEntry(Map.Entry<String, Map<String, String>> eldes
358359
BigQueryConnectionProperty.newBuilder()
359360
.setName(PROJECT_ID_PROPERTY_NAME)
360361
.setDescription("A globally unique identifier for your project.")
361-
.setDefaultValue(BigQueryOptions.getDefaultProjectId())
362+
.setLazyDefaultValue(() -> BigQueryOptions.getDefaultProjectId())
362363
.build(),
363364
BigQueryConnectionProperty.newBuilder()
364365
.setName(LOG_PATH_PROPERTY_NAME)

google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
2222
import com.google.api.gax.rpc.HeaderProvider;
2323
import com.google.api.gax.rpc.TransportChannelProvider;
24+
import com.google.cloud.bigquery.BigQuery;
25+
import com.google.cloud.bigquery.QueryJobConfiguration.JobCreationMode;
2426
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
2527
import com.google.cloud.bigquery.storage.v1.BigQueryReadClient;
2628
import com.google.cloud.bigquery.storage.v1.BigQueryWriteClient;
@@ -35,6 +37,9 @@ public class BigQueryConnectionTest {
3537

3638
private static final String DEFAULT_VERSION = "0.0.0";
3739
private static final String DEFAULT_JDBC_TOKEN_VALUE = "Google-BigQuery-JDBC-Driver";
40+
private static final String BASE_URL =
41+
"jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
42+
+ "OAuthType=2;OAuthAccessToken=redacted;ProjectId=project;";
3843
private String expectedVersion;
3944

4045
@Before
@@ -378,4 +383,34 @@ public void testBigQueryReadClientKeepAliveSettings() throws SQLException, IOExc
378383
assertTrue(grpcProvider.getKeepAliveWithoutCalls());
379384
}
380385
}
386+
387+
@Test
388+
public void testBigQueryJobCreationMode_required() throws Exception {
389+
String url = BASE_URL + "JobCreationMode=1;";
390+
try (BigQueryConnection connection = new BigQueryConnection(url)) {
391+
BigQuery bq = connection.getBigQuery();
392+
assertEquals(
393+
bq.getOptions().getDefaultJobCreationMode(), JobCreationMode.JOB_CREATION_REQUIRED);
394+
}
395+
}
396+
397+
@Test
398+
public void testBigQueryJobCreationMode_optional() throws Exception {
399+
String url = BASE_URL + "JobCreationMode=2;";
400+
try (BigQueryConnection connection = new BigQueryConnection(url)) {
401+
BigQuery bq = connection.getBigQuery();
402+
assertEquals(
403+
bq.getOptions().getDefaultJobCreationMode(), JobCreationMode.JOB_CREATION_OPTIONAL);
404+
}
405+
}
406+
407+
@Test
408+
public void testBigQueryJobCreationMode_default() throws Exception {
409+
String url = BASE_URL;
410+
try (BigQueryConnection connection = new BigQueryConnection(url)) {
411+
BigQuery bq = connection.getBigQuery();
412+
assertEquals(
413+
bq.getOptions().getDefaultJobCreationMode(), JobCreationMode.JOB_CREATION_OPTIONAL);
414+
}
415+
}
381416
}

google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.net.URI;
3333
import java.net.URISyntaxException;
3434
import java.net.URL;
35+
import java.nio.file.Files;
3536
import java.nio.file.Paths;
3637
import java.security.PrivateKey;
3738
import java.util.Collections;
@@ -501,31 +502,25 @@ public void testPrivateKeyFromPkcs8_wrong() {
501502
// keytool -genkey -alias privatekey -keyalg RSA -keysize 2048 -storepass notasecret \
502503
// -keypass notasecret -storetype pkcs12 -keystore ./fake.p12
503504
@Test
504-
public void testPrivateKeyFromP12File() {
505+
public void testPrivateKeyFromP12Bytes() {
505506
URL resource = BigQueryJdbcOAuthUtilityTest.class.getResource("/fake.p12");
506507
try {
507508
PrivateKey pk =
508-
BigQueryJdbcOAuthUtility.privateKeyFromP12File(
509-
Paths.get(resource.toURI()).toAbsolutePath().toString(), "notasecret");
509+
BigQueryJdbcOAuthUtility.privateKeyFromP12Bytes(
510+
Files.readAllBytes(Paths.get(resource.toURI())), "notasecret");
510511
assertNotNull(pk);
511512
} catch (Exception e) {
512513
assertTrue(false);
513514
}
514515
}
515516

516517
@Test
517-
public void testPrivateKeyFromP12File_missing_file() {
518-
PrivateKey pk = BigQueryJdbcOAuthUtility.privateKeyFromP12File("", "");
519-
assertNull(pk);
520-
}
521-
522-
@Test
523-
public void testPrivateKeyFromP12File_wrong_password() {
518+
public void testPrivateKeyFromP12Bytes_wrong_password() {
524519
URL resource = BigQueryJdbcOAuthUtilityTest.class.getResource("/fake.p12");
525520
try {
526521
PrivateKey pk =
527-
BigQueryJdbcOAuthUtility.privateKeyFromP12File(
528-
Paths.get(resource.toURI()).toAbsolutePath().toString(), "fake");
522+
BigQueryJdbcOAuthUtility.privateKeyFromP12Bytes(
523+
Files.readAllBytes(Paths.get(resource.toURI())), "fake");
529524
assertNull(pk);
530525
} catch (Exception e) {
531526
assertTrue(false);

0 commit comments

Comments
 (0)