Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion framework/db/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,17 @@
<configuration>
<excludes>
<exclude>com/cloud/utils/testcase/*TestCase*</exclude>
<exclude>com/cloud/utils/db/*Test*</exclude>
<!-- The test classes below are excluded because they require a live database. The remaining
ones in com/cloud/utils/db are plain unit tests and must run in the build. -->
<exclude>com/cloud/utils/db/DbTest*</exclude>
<exclude>com/cloud/utils/db/ElementCollectionTest*</exclude>
<exclude>com/cloud/utils/db/FilterTest*</exclude>
<exclude>com/cloud/utils/db/GenericDaoBaseTest*</exclude>
<exclude>com/cloud/utils/db/GlobalLockTest*</exclude>
<exclude>com/cloud/utils/db/GroupByTest*</exclude>
<exclude>com/cloud/utils/db/Merovingian2Test*</exclude>
<exclude>com/cloud/utils/db/TestTransaction*</exclude>
<exclude>com/cloud/utils/db/TransactionContextBuilderTest*</exclude>
</excludes>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Properties;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;

import javax.sql.DataSource;

Expand Down Expand Up @@ -87,6 +88,17 @@ public class TransactionLegacy implements Closeable {
public static final short CONNECTED_DB = -1;
public static final String CONNECTION_PARAMS = "scrollTolerantForwardOnly=true";

/**
* Format of the pattern that matches a parameter of a connection URI: the name must be at the start of the URI
* parameters or right after a parameter separator, and must be followed by "=". Searching for the bare name would
* consider the parameter as configured when it is just part of a host, of a database name or of the value of
* another parameter.
*/
private static final String URI_PARAM_PATTERN_FORMAT = "(?:^|[?&])%s=";
private static final String CONNECTION_COLLATION_PARAM = "connectionCollation";
private static final String CHARACTER_ENCODING_PARAM = "characterEncoding";
private static final String DEFAULT_CONNECTION_COLLATION = "utf8mb4_general_ci";

private static AtomicLong s_id = new AtomicLong();
private static final TransactionMBeanImpl s_mbean = new TransactionMBeanImpl();
static {
Expand Down Expand Up @@ -1196,6 +1208,9 @@ protected static Pair<String, String> getConnectionUriAndDriver(Properties dbPro

connectionUri = propertyUri;
}

connectionUri = addDefaultConnectionCollation(connectionUri);

LOGGER.info("Using the following URI to connect to {} database [{}].", schema, connectionUri);
return new Pair<>(connectionUri, driver);
}
Expand Down Expand Up @@ -1260,6 +1275,48 @@ protected static String buildConnectionUri(String loadBalanceStrategy, String dr
return connectionUri.toString();
}

/**
* Informs whether {@link #DEFAULT_CONNECTION_COLLATION} should be added to a connection URI. It is only added for
* connections that do not already define the charset or the collation, either through {@code db.<schema>.url.params}
* or directly in {@code db.<schema>.uri}.
*
* @param connectionUri the connection URI configured by the operator.
*/
protected static boolean shouldPinConnectionCollation(String connectionUri) {
return !containsUriParam(connectionUri, CONNECTION_COLLATION_PARAM)
&& !containsUriParam(connectionUri, CHARACTER_ENCODING_PARAM);
}

/**
* Informs whether the given parameter is defined in the connection URI.
*
* @param connectionUri the connection URI configured by the operator; it also accepts only the parameters of a URI,
* as in {@code db.<schema>.url.params};
* @param param the name of the parameter to look for.
*/
protected static boolean containsUriParam(String connectionUri, String param) {
Pattern pattern = Pattern.compile(String.format(URI_PARAM_PATTERN_FORMAT, Pattern.quote(param)), Pattern.CASE_INSENSITIVE);
return pattern.matcher(StringUtils.defaultString(connectionUri)).find();
}

/**
* Adds {@link #DEFAULT_CONNECTION_COLLATION} to a connection URI configured either through
* {@code db.<schema>.url.params} or directly in {@code db.<schema>.uri}, keeping the URI untouched if the operator
* already defined the charset or the collation in it.
*/
protected static String addDefaultConnectionCollation(String connectionUri) {
if (!shouldPinConnectionCollation(connectionUri)) {
return connectionUri;
}

String separator = "?";
if (StringUtils.contains(connectionUri, "?")) {
separator = StringUtils.endsWithAny(connectionUri, "?", "&") ? StringUtils.EMPTY : "&";
}

return String.format("%s%s%s=%s", connectionUri, separator, CONNECTION_COLLATION_PARAM, DEFAULT_CONNECTION_COLLATION);
}

/**
* Creates a data source
*/
Expand Down
Loading
Loading