112112import com .google .cloud .spanner .connection .ClientSideStatementValueConverters .StringValueConverter ;
113113import com .google .cloud .spanner .connection .ConnectionProperty .Context ;
114114import com .google .cloud .spanner .connection .DirectedReadOptionsUtil .DirectedReadOptionsConverter ;
115+ import com .google .common .collect .ImmutableList ;
115116import com .google .common .collect .ImmutableMap ;
116117import com .google .spanner .v1 .DirectedReadOptions ;
117118import 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. */
0 commit comments