Skip to content

Commit 82f88ba

Browse files
committed
refactor: add internal data structures for transactional connection state
This change adds internal data structures that can be used for transactional connection state. These data structures also reduces the amount of code that is needed for each connection property that is added. Connection properties are currently represented as actual variables in the ConnectionImpl class. These new data structures removes the need for that. Only the connection property retryAbortsInternally is refactored to use the new data structure. All other connection properties will be refactored in a following change, in order to keep each change as small as possible. The data structure supports both transactional and non-transactional connection state. Transactional state is disabled in the current version in order to be consistent with the current behavior. It will be enabled in a later change when all connection properties have been refactored to use the new data structure.
1 parent 5276c5e commit 82f88ba

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.spanner.connection;
18+
19+
import static com.google.cloud.spanner.connection.ConnectionOptions.AUTOCOMMIT_PROPERTY_NAME;
20+
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_AUTOCOMMIT;
21+
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_READONLY;
22+
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_RETRY_ABORTS_INTERNALLY;
23+
import static com.google.cloud.spanner.connection.ConnectionOptions.READONLY_PROPERTY_NAME;
24+
import static com.google.cloud.spanner.connection.ConnectionOptions.RETRY_ABORTS_INTERNALLY_PROPERTY_NAME;
25+
import static com.google.cloud.spanner.connection.ConnectionProperty.castProperty;
26+
27+
import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.AutocommitDmlModeConverter;
28+
import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.BooleanConverter;
29+
import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.ConnectionStateTypeConverter;
30+
import com.google.cloud.spanner.connection.ConnectionProperty.Context;
31+
import com.google.common.collect.ImmutableMap;
32+
import java.util.Collections;
33+
import java.util.HashMap;
34+
import java.util.Map;
35+
36+
/**
37+
* Utility class that defines all known connection properties. This class will eventually replace
38+
* the list of {@link com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty} in
39+
* {@link ConnectionOptions}.
40+
*/
41+
class CoreConnectionProperties {
42+
private static final Map<String, ConnectionProperty<?>> INTERNAL_CORE_CONNECTION_PROPERTIES =
43+
new HashMap<>();
44+
45+
static final ConnectionProperty<ConnectionState.Type> CONNECTION_STATE_TYPE =
46+
create(
47+
"connectionStateType",
48+
"The type of connection state to use for this connection. Can only be set at start up. "
49+
+ "If no value is set, then the database dialect default will be used, "
50+
+ "which is NON_TRANSACTIONAL for GoogleSQL and TRANSACTIONAL for PostgreSQL.",
51+
null,
52+
ConnectionStateTypeConverter.INSTANCE,
53+
Context.STARTUP);
54+
static final ConnectionProperty<Boolean> AUTOCOMMIT =
55+
create(
56+
AUTOCOMMIT_PROPERTY_NAME,
57+
"Should the connection start in autocommit (true/false)",
58+
DEFAULT_AUTOCOMMIT,
59+
BooleanConverter.INSTANCE,
60+
Context.IN_TRANSACTION);
61+
static final ConnectionProperty<Boolean> READONLY =
62+
create(
63+
READONLY_PROPERTY_NAME,
64+
"Should the connection start in read-only mode (true/false)",
65+
DEFAULT_READONLY,
66+
BooleanConverter.INSTANCE,
67+
Context.IN_TRANSACTION);
68+
static final ConnectionProperty<AutocommitDmlMode> AUTOCOMMIT_DML_MODE =
69+
create(
70+
"autocommit_dml_mode",
71+
"Should the connection automatically retry Aborted errors (true/false)",
72+
AutocommitDmlMode.TRANSACTIONAL,
73+
AutocommitDmlModeConverter.INSTANCE,
74+
Context.OUTSIDE_TRANSACTION);
75+
static final ConnectionProperty<Boolean> RETRY_ABORTS_INTERNALLY =
76+
create(
77+
RETRY_ABORTS_INTERNALLY_PROPERTY_NAME,
78+
"Should the connection automatically retry Aborted errors (true/false)",
79+
DEFAULT_RETRY_ABORTS_INTERNALLY,
80+
BooleanConverter.INSTANCE,
81+
Context.IN_TRANSACTION);
82+
83+
static final Map<String, ConnectionProperty<?>> CORE_CONNECTION_PROPERTIES =
84+
Collections.unmodifiableMap(INTERNAL_CORE_CONNECTION_PROPERTIES);
85+
86+
/** Utility method for creating a new core {@link ConnectionProperty}. */
87+
private static <T> ConnectionProperty<T> create(
88+
String name,
89+
String description,
90+
T defaultValue,
91+
ClientSideStatementValueConverter<T> converter,
92+
Context context) {
93+
ConnectionProperty<T> property =
94+
ConnectionProperty.create(name, description, defaultValue, converter, context);
95+
INTERNAL_CORE_CONNECTION_PROPERTIES.put(property.getKey(), property);
96+
return property;
97+
}
98+
99+
/** Parse the connection properties that can be found in the given connection URL. */
100+
static ImmutableMap<String, ConnectionPropertyValue<?>> parseValues(String url) {
101+
ImmutableMap.Builder<String, ConnectionPropertyValue<?>> builder = ImmutableMap.builder();
102+
for (ConnectionProperty<?> property : CORE_CONNECTION_PROPERTIES.values()) {
103+
ConnectionPropertyValue<?> value = parseValue(castProperty(property), url);
104+
if (value != null) {
105+
builder.put(property.getKey(), value);
106+
}
107+
}
108+
return builder.build();
109+
}
110+
111+
/**
112+
* Parse and convert the value of the specific connection property from a connection URL (e.g.
113+
* readonly=true).
114+
*/
115+
private static <T> ConnectionPropertyValue<T> parseValue(
116+
ConnectionProperty<T> property, String url) {
117+
String stringValue = ConnectionOptions.parseUriProperty(url, property.getKey());
118+
return property.convert(stringValue);
119+
}
120+
121+
/** This class should not be instantiated. */
122+
private CoreConnectionProperties() {}
123+
}

0 commit comments

Comments
 (0)