Skip to content

Commit 109f8fc

Browse files
olavloiterahul2393
andauthored
chore: make valid connection properties public (#3546)
Make the list of valid connection properties public, so tools that depend on the Connection API can use this to for example generate documentation for valid properties. Also add valid values to the connection properties that have that (e.g. enums and booleans). Co-authored-by: rahul2393 <[email protected]>
1 parent 432fc4e commit 109f8fc

File tree

2 files changed

+86
-18
lines changed

2 files changed

+86
-18
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionProperties.java

+60-8
Original file line numberDiff line numberDiff line change
@@ -112,27 +112,30 @@
112112
import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.StringValueConverter;
113113
import com.google.cloud.spanner.connection.ConnectionProperty.Context;
114114
import com.google.cloud.spanner.connection.DirectedReadOptionsUtil.DirectedReadOptionsConverter;
115+
import com.google.common.collect.ImmutableList;
115116
import com.google.common.collect.ImmutableMap;
116117
import com.google.spanner.v1.DirectedReadOptions;
117118
import java.time.Duration;
118-
import java.util.Map;
119119

120120
/**
121121
* Utility class that defines all known connection properties. This class will eventually replace
122122
* the list of {@link com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty} in
123123
* {@link ConnectionOptions}.
124124
*/
125-
class ConnectionProperties {
125+
public class ConnectionProperties {
126126
private static final ImmutableMap.Builder<String, ConnectionProperty<?>>
127127
CONNECTION_PROPERTIES_BUILDER = ImmutableMap.builder();
128128

129+
private static final Boolean[] BOOLEANS = new Boolean[] {Boolean.TRUE, Boolean.FALSE};
130+
129131
static final ConnectionProperty<ConnectionState.Type> CONNECTION_STATE_TYPE =
130132
create(
131133
"connection_state_type",
132134
"The type of connection state to use for this connection. Can only be set at start up. "
133135
+ "If no value is set, then the database dialect default will be used, "
134136
+ "which is NON_TRANSACTIONAL for GoogleSQL and TRANSACTIONAL for PostgreSQL.",
135137
null,
138+
ConnectionState.Type.values(),
136139
ConnectionStateTypeConverter.INSTANCE,
137140
Context.STARTUP);
138141
static final ConnectionProperty<String> TRACING_PREFIX =
@@ -148,6 +151,7 @@ class ConnectionProperties {
148151
LENIENT_PROPERTY_NAME,
149152
"Silently ignore unknown properties in the connection string/properties (true/false)",
150153
DEFAULT_LENIENT,
154+
BOOLEANS,
151155
BooleanConverter.INSTANCE,
152156
Context.STARTUP);
153157
static final ConnectionProperty<String> ENDPOINT =
@@ -167,6 +171,7 @@ class ConnectionProperties {
167171
+ "The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. "
168172
+ "Add dialect=postgresql to the connection string to make sure that the database that is created uses the PostgreSQL dialect.",
169173
false,
174+
BOOLEANS,
170175
BooleanConverter.INSTANCE,
171176
Context.STARTUP);
172177
static final ConnectionProperty<Boolean> USE_AUTO_SAVEPOINTS_FOR_EMULATOR =
@@ -175,13 +180,15 @@ class ConnectionProperties {
175180
"Automatically creates savepoints for each statement in a read/write transaction when using the Emulator. "
176181
+ "This is no longer needed when using Emulator version 1.5.23 or higher.",
177182
false,
183+
BOOLEANS,
178184
BooleanConverter.INSTANCE,
179185
Context.STARTUP);
180186
static final ConnectionProperty<Boolean> USE_PLAIN_TEXT =
181187
create(
182188
USE_PLAIN_TEXT_PROPERTY_NAME,
183189
"Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator.",
184190
DEFAULT_USE_PLAIN_TEXT,
191+
BOOLEANS,
185192
BooleanConverter.INSTANCE,
186193
Context.STARTUP);
187194

@@ -226,6 +233,7 @@ class ConnectionProperties {
226233
DIALECT_PROPERTY_NAME,
227234
"Sets the dialect to use for new databases that are created by this connection.",
228235
Dialect.GOOGLE_STANDARD_SQL,
236+
Dialect.values(),
229237
DialectConverter.INSTANCE,
230238
Context.STARTUP);
231239
static final ConnectionProperty<Boolean> TRACK_SESSION_LEAKS =
@@ -238,6 +246,7 @@ class ConnectionProperties {
238246
+ "actual session leak is detected. The stack trace of the exception will "
239247
+ "in that case not contain the call stack of when the session was checked out.",
240248
DEFAULT_TRACK_SESSION_LEAKS,
249+
BOOLEANS,
241250
BooleanConverter.INSTANCE,
242251
Context.STARTUP);
243252
static final ConnectionProperty<Boolean> TRACK_CONNECTION_LEAKS =
@@ -250,13 +259,15 @@ class ConnectionProperties {
250259
+ "actual connection leak is detected. The stack trace of the exception will "
251260
+ "in that case not contain the call stack of when the connection was created.",
252261
DEFAULT_TRACK_CONNECTION_LEAKS,
262+
BOOLEANS,
253263
BooleanConverter.INSTANCE,
254264
Context.STARTUP);
255265
static final ConnectionProperty<Boolean> ROUTE_TO_LEADER =
256266
create(
257267
ROUTE_TO_LEADER_PROPERTY_NAME,
258268
"Should read/write transactions and partitioned DML be routed to leader region (true/false)",
259269
DEFAULT_ROUTE_TO_LEADER,
270+
BOOLEANS,
260271
BooleanConverter.INSTANCE,
261272
Context.STARTUP);
262273
static final ConnectionProperty<Boolean> USE_VIRTUAL_THREADS =
@@ -265,6 +276,7 @@ class ConnectionProperties {
265276
"Use a virtual thread instead of a platform thread for each connection (true/false). "
266277
+ "This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored.",
267278
DEFAULT_USE_VIRTUAL_THREADS,
279+
BOOLEANS,
268280
BooleanConverter.INSTANCE,
269281
Context.STARTUP);
270282
static final ConnectionProperty<Boolean> USE_VIRTUAL_GRPC_TRANSPORT_THREADS =
@@ -273,6 +285,7 @@ class ConnectionProperties {
273285
"Use a virtual thread instead of a platform thread for the gRPC executor (true/false). "
274286
+ "This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored.",
275287
DEFAULT_USE_VIRTUAL_GRPC_TRANSPORT_THREADS,
288+
BOOLEANS,
276289
BooleanConverter.INSTANCE,
277290
Context.STARTUP);
278291
static final ConnectionProperty<Boolean> ENABLE_EXTENDED_TRACING =
@@ -282,6 +295,7 @@ class ConnectionProperties {
282295
+ "by this connection. The SQL string is added as the standard OpenTelemetry "
283296
+ "attribute 'db.statement'.",
284297
DEFAULT_ENABLE_EXTENDED_TRACING,
298+
BOOLEANS,
285299
BooleanConverter.INSTANCE,
286300
Context.STARTUP);
287301
static final ConnectionProperty<Boolean> ENABLE_API_TRACING =
@@ -292,6 +306,7 @@ class ConnectionProperties {
292306
+ "or if you want to debug potential latency problems caused by RPCs that are "
293307
+ "being retried.",
294308
DEFAULT_ENABLE_API_TRACING,
309+
BOOLEANS,
295310
BooleanConverter.INSTANCE,
296311
Context.STARTUP);
297312
static final ConnectionProperty<Boolean> ENABLE_END_TO_END_TRACING =
@@ -302,6 +317,7 @@ class ConnectionProperties {
302317
+ "Server side traces can only go to Google Cloud Trace, so to see end to end traces, "
303318
+ "the application should configure an exporter that exports the traces to Google Cloud Trace.",
304319
DEFAULT_ENABLE_END_TO_END_TRACING,
320+
BOOLEANS,
305321
BooleanConverter.INSTANCE,
306322
Context.STARTUP);
307323
static final ConnectionProperty<Integer> MIN_SESSIONS =
@@ -345,20 +361,24 @@ class ConnectionProperties {
345361
AUTOCOMMIT_PROPERTY_NAME,
346362
"Should the connection start in autocommit (true/false)",
347363
DEFAULT_AUTOCOMMIT,
364+
BOOLEANS,
348365
BooleanConverter.INSTANCE,
349366
Context.USER);
350367
static final ConnectionProperty<Boolean> READONLY =
351368
create(
352369
READONLY_PROPERTY_NAME,
353370
"Should the connection start in read-only mode (true/false)",
354371
DEFAULT_READONLY,
372+
BOOLEANS,
355373
BooleanConverter.INSTANCE,
356374
Context.USER);
357375
static final ConnectionProperty<AutocommitDmlMode> AUTOCOMMIT_DML_MODE =
358376
create(
359377
"autocommit_dml_mode",
360-
"Should the connection automatically retry Aborted errors (true/false)",
378+
"Determines the transaction type that is used to execute "
379+
+ "DML statements when the connection is in auto-commit mode.",
361380
AutocommitDmlMode.TRANSACTIONAL,
381+
AutocommitDmlMode.values(),
362382
AutocommitDmlModeConverter.INSTANCE,
363383
Context.USER);
364384
static final ConnectionProperty<Boolean> RETRY_ABORTS_INTERNALLY =
@@ -371,13 +391,15 @@ class ConnectionProperties {
371391
RETRY_ABORTS_INTERNALLY_PROPERTY_NAME,
372392
"Should the connection automatically retry Aborted errors (true/false)",
373393
DEFAULT_RETRY_ABORTS_INTERNALLY,
394+
BOOLEANS,
374395
BooleanConverter.INSTANCE,
375396
Context.USER);
376397
static final ConnectionProperty<Boolean> RETURN_COMMIT_STATS =
377398
create(
378399
"returnCommitStats",
379400
"Request that Spanner returns commit statistics for read/write transactions (true/false)",
380401
DEFAULT_RETURN_COMMIT_STATS,
402+
BOOLEANS,
381403
BooleanConverter.INSTANCE,
382404
Context.USER);
383405
static final ConnectionProperty<Boolean> DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE =
@@ -389,6 +411,7 @@ class ConnectionProperties {
389411
+ "the first write operation in a read/write transaction will be executed using the read/write transaction. Enabling this mode can reduce locking "
390412
+ "and improve performance for applications that can handle the lower transaction isolation semantics.",
391413
DEFAULT_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE,
414+
BOOLEANS,
392415
BooleanConverter.INSTANCE,
393416
Context.USER);
394417
static final ConnectionProperty<Boolean> KEEP_TRANSACTION_ALIVE =
@@ -398,6 +421,7 @@ class ConnectionProperties {
398421
+ "if no other statements are being executed. This option should be used with caution, as it can keep transactions alive and hold on to locks "
399422
+ "longer than intended. This option should typically be used for CLI-type application that might wait for user input for a longer period of time.",
400423
DEFAULT_KEEP_TRANSACTION_ALIVE,
424+
BOOLEANS,
401425
BooleanConverter.INSTANCE,
402426
Context.USER);
403427

@@ -415,6 +439,7 @@ class ConnectionProperties {
415439
+ "Executing a query that cannot be partitioned will fail. "
416440
+ "Executing a query in a read/write transaction will also fail.",
417441
DEFAULT_AUTO_PARTITION_MODE,
442+
BOOLEANS,
418443
BooleanConverter.INSTANCE,
419444
Context.USER);
420445
static final ConnectionProperty<Boolean> DATA_BOOST_ENABLED =
@@ -423,6 +448,7 @@ class ConnectionProperties {
423448
"Enable data boost for all partitioned queries that are executed by this connection. "
424449
+ "This setting is only used for partitioned queries and is ignored by all other statements.",
425450
DEFAULT_DATA_BOOST_ENABLED,
451+
BOOLEANS,
426452
BooleanConverter.INSTANCE,
427453
Context.USER);
428454
static final ConnectionProperty<Integer> MAX_PARTITIONS =
@@ -468,20 +494,23 @@ class ConnectionProperties {
468494
RPC_PRIORITY_NAME,
469495
"Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH.",
470496
DEFAULT_RPC_PRIORITY,
497+
RpcPriority.values(),
471498
RpcPriorityConverter.INSTANCE,
472499
Context.USER);
473500
static final ConnectionProperty<SavepointSupport> SAVEPOINT_SUPPORT =
474501
create(
475502
"savepoint_support",
476503
"Determines the behavior of the connection when savepoints are used.",
477504
SavepointSupport.FAIL_AFTER_ROLLBACK,
505+
SavepointSupport.values(),
478506
SavepointSupportConverter.INSTANCE,
479507
Context.USER);
480508
static final ConnectionProperty<DdlInTransactionMode> DDL_IN_TRANSACTION_MODE =
481509
create(
482510
DDL_IN_TRANSACTION_MODE_PROPERTY_NAME,
483511
"Determines how the connection should handle DDL statements in a read/write transaction.",
484512
DEFAULT_DDL_IN_TRANSACTION_MODE,
513+
DdlInTransactionMode.values(),
485514
DdlInTransactionModeConverter.INSTANCE,
486515
Context.USER);
487516
static final ConnectionProperty<Duration> MAX_COMMIT_DELAY =
@@ -504,6 +533,7 @@ class ConnectionProperties {
504533
+ "This setting is only in read/write transactions. DML statements in auto-commit mode "
505534
+ "are executed directly.",
506535
DEFAULT_AUTO_BATCH_DML,
536+
BOOLEANS,
507537
BooleanConverter.INSTANCE,
508538
Context.USER);
509539
static final ConnectionProperty<Long> AUTO_BATCH_DML_UPDATE_COUNT =
@@ -538,23 +568,45 @@ class ConnectionProperties {
538568
+ AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION_PROPERTY_NAME
539569
+ " to false.",
540570
DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION,
571+
BOOLEANS,
541572
BooleanConverter.INSTANCE,
542573
Context.USER);
543574

544-
static final Map<String, ConnectionProperty<?>> CONNECTION_PROPERTIES =
575+
static final ImmutableMap<String, ConnectionProperty<?>> CONNECTION_PROPERTIES =
545576
CONNECTION_PROPERTIES_BUILDER.build();
546577

578+
/** The list of all supported connection properties. */
579+
public static ImmutableList<ConnectionProperty<?>> VALID_CONNECTION_PROPERTIES =
580+
ImmutableList.copyOf(ConnectionProperties.CONNECTION_PROPERTIES.values());
581+
547582
/** Utility method for creating a new core {@link ConnectionProperty}. */
548583
private static <T> ConnectionProperty<T> create(
549584
String name,
550585
String description,
551586
T defaultValue,
552587
ClientSideStatementValueConverter<T> converter,
553588
Context context) {
554-
ConnectionProperty<T> property =
555-
ConnectionProperty.create(name, description, defaultValue, converter, context);
556-
CONNECTION_PROPERTIES_BUILDER.put(property.getKey(), property);
557-
return property;
589+
return create(name, description, defaultValue, null, converter, context);
590+
}
591+
592+
/** Utility method for creating a new core {@link ConnectionProperty}. */
593+
private static <T> ConnectionProperty<T> create(
594+
String name,
595+
String description,
596+
T defaultValue,
597+
T[] validValues,
598+
ClientSideStatementValueConverter<T> converter,
599+
Context context) {
600+
try {
601+
ConnectionProperty<T> property =
602+
ConnectionProperty.create(
603+
name, description, defaultValue, validValues, converter, context);
604+
CONNECTION_PROPERTIES_BUILDER.put(property.getKey(), property);
605+
return property;
606+
} catch (Throwable t) {
607+
t.printStackTrace();
608+
}
609+
return null;
558610
}
559611

560612
/** Parse the connection properties that can be found in the given connection URL. */

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionProperty.java

+26-10
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@
3737
* connection state is an opt-in.
3838
*/
3939
public class ConnectionProperty<T> {
40+
4041
/**
4142
* Context indicates when a {@link ConnectionProperty} may be set. Each higher-ordinal value
4243
* includes the preceding values, meaning that a {@link ConnectionProperty} with {@link
4344
* Context#USER} can be set both at connection startup and during the connection's lifetime.
4445
*/
45-
enum Context {
46+
public enum Context {
4647
/** The property can only be set at startup of the connection. */
4748
STARTUP,
4849
/**
@@ -79,8 +80,20 @@ static <T> ConnectionProperty<T> create(
7980
T defaultValue,
8081
ClientSideStatementValueConverter<T> converter,
8182
Context context) {
83+
return create(name, description, defaultValue, null, converter, context);
84+
}
85+
86+
/** Utility method for creating a typed {@link ConnectionProperty}. */
87+
@Nonnull
88+
static <T> ConnectionProperty<T> create(
89+
@Nonnull String name,
90+
String description,
91+
T defaultValue,
92+
T[] validValues,
93+
ClientSideStatementValueConverter<T> converter,
94+
Context context) {
8295
return new ConnectionProperty<>(
83-
null, name, description, defaultValue, null, converter, context);
96+
null, name, description, defaultValue, validValues, converter, context);
8497
}
8598

8699
/**
@@ -163,35 +176,38 @@ ConnectionPropertyValue<T> convert(@Nullable String stringValue) {
163176
return new ConnectionPropertyValue<>(this, convertedValue, convertedValue);
164177
}
165178

166-
String getKey() {
179+
@Nonnull
180+
public String getKey() {
167181
return this.key;
168182
}
169183

170-
boolean hasExtension() {
184+
public boolean hasExtension() {
171185
return this.extension != null;
172186
}
173187

174-
String getExtension() {
188+
public String getExtension() {
175189
return this.extension;
176190
}
177191

178-
String getName() {
192+
@Nonnull
193+
public String getName() {
179194
return this.name;
180195
}
181196

182-
String getDescription() {
197+
@Nonnull
198+
public String getDescription() {
183199
return this.description;
184200
}
185201

186-
T getDefaultValue() {
202+
public T getDefaultValue() {
187203
return this.defaultValue;
188204
}
189205

190-
T[] getValidValues() {
206+
public T[] getValidValues() {
191207
return this.validValues;
192208
}
193209

194-
Context getContext() {
210+
public Context getContext() {
195211
return this.context;
196212
}
197213
}

0 commit comments

Comments
 (0)