mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-02 02:34:42 +08:00
fix(agents): sanitize backtick identifier quote for GBase 8s
This commit is contained in:
@@ -454,7 +454,57 @@ public abstract class AbstractJdbcAgent extends BaseDatabaseAgent {
|
||||
}
|
||||
try {
|
||||
String quote = connection.getMetaData().getIdentifierQuoteString();
|
||||
return quote == null || quote.trim().isEmpty() ? "" : quote.trim();
|
||||
if (quote == null || quote.trim().isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return sanitizeInformixFamilyBacktickQuote(params, connection, quote.trim());
|
||||
} catch (Exception ignored) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// GBase 8s and other Informix-family JDBC drivers report "`" from
|
||||
// getIdentifierQuoteString() even though their servers reject backtick-quoted
|
||||
// identifiers with "illegal character in statement" outside MySQL compatibility
|
||||
// mode (SQLMODE=mysql). An empty quote makes clients emit unquoted identifiers,
|
||||
// which both SQL modes accept.
|
||||
private static String sanitizeInformixFamilyBacktickQuote(ConnectParams params, Connection connection, String quote) {
|
||||
if (!"`".equals(quote) || !isInformixFamilyJdbc(params, connection) || isInformixFamilyMysqlCompat(params, connection)) {
|
||||
return quote;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static boolean isInformixFamilyJdbc(ConnectParams params, Connection connection) {
|
||||
StringBuilder identity = new StringBuilder();
|
||||
appendJdbcIdentity(identity, params.getConnection_string());
|
||||
appendJdbcIdentity(identity, params.getJdbc_driver_class());
|
||||
List<String> driverPaths = params.getJdbc_driver_paths();
|
||||
if (driverPaths != null) {
|
||||
for (String path : driverPaths) {
|
||||
appendJdbcIdentity(identity, path);
|
||||
}
|
||||
}
|
||||
appendJdbcIdentity(identity, connectionUrl(connection));
|
||||
String normalized = identity.toString().toLowerCase(Locale.ROOT);
|
||||
return normalized.contains("jdbc:gbasedbt")
|
||||
|| normalized.contains("jdbc:informix")
|
||||
|| normalized.contains("com.gbasedbt")
|
||||
|| normalized.contains("com.informix");
|
||||
}
|
||||
|
||||
private static boolean isInformixFamilyMysqlCompat(ConnectParams params, Connection connection) {
|
||||
if (params.isMysql_compat_mode()) {
|
||||
return true;
|
||||
}
|
||||
String identity = (params.getConnection_string() + "\n" + connectionUrl(connection)).toLowerCase(Locale.ROOT);
|
||||
return identity.contains("sqlmode=mysql");
|
||||
}
|
||||
|
||||
private static String connectionUrl(Connection connection) {
|
||||
try {
|
||||
String url = connection.getMetaData().getURL();
|
||||
return url == null ? "" : url;
|
||||
} catch (Exception ignored) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -115,6 +115,55 @@ class AbstractJdbcAgentTest {
|
||||
assertEquals(0, tracking.compatibilityQueryCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void ignoresGbase8sDriverBacktickIdentifierQuote() {
|
||||
TrackingConnection tracking = new TrackingConnection();
|
||||
tracking.identifierQuote = "`";
|
||||
tracking.jdbcUrl = "jdbc:gbasedbt-sqli://localhost:9088/appdb:GBASEDBTSERVER=gbase8s";
|
||||
TestAgent agent = new TestAgent(tracking);
|
||||
|
||||
agent.connect(new ConnectParams());
|
||||
|
||||
assertEquals("", agent.getIdentifierQuote());
|
||||
}
|
||||
|
||||
@Test
|
||||
void ignoresBacktickQuoteForInformixFamilyConnectionString() {
|
||||
TrackingConnection tracking = new TrackingConnection();
|
||||
tracking.identifierQuote = "`";
|
||||
TestAgent agent = new TestAgent(tracking);
|
||||
|
||||
ConnectParams params = new ConnectParams();
|
||||
params.setConnection_string("jdbc:informix-sqli://localhost:9088/appdb:INFORMIXSERVER=ol_informix");
|
||||
agent.connect(params);
|
||||
|
||||
assertEquals("", agent.getIdentifierQuote());
|
||||
}
|
||||
|
||||
@Test
|
||||
void keepsInformixFamilyBacktickQuoteInMysqlCompatMode() {
|
||||
TrackingConnection tracking = new TrackingConnection();
|
||||
tracking.identifierQuote = "`";
|
||||
tracking.jdbcUrl = "jdbc:gbasedbt-sqli://localhost:9088/appdb:GBASEDBTSERVER=gbase8s;SQLMODE=mysql";
|
||||
TestAgent agent = new TestAgent(tracking);
|
||||
|
||||
agent.connect(new ConnectParams());
|
||||
|
||||
assertEquals("`", agent.getIdentifierQuote());
|
||||
}
|
||||
|
||||
@Test
|
||||
void keepsNonBacktickQuotesForInformixFamilyDrivers() {
|
||||
TrackingConnection tracking = new TrackingConnection();
|
||||
tracking.identifierQuote = "\"";
|
||||
tracking.jdbcUrl = "jdbc:gbasedbt-sqli://localhost:9088/appdb:GBASEDBTSERVER=gbase8s";
|
||||
TestAgent agent = new TestAgent(tracking);
|
||||
|
||||
agent.connect(new ConnectParams());
|
||||
|
||||
assertEquals("\"", agent.getIdentifierQuote());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testsConnectionsThroughSharedLifecycle() {
|
||||
TrackingConnection tracking = new TrackingConnection();
|
||||
@@ -469,6 +518,7 @@ class AbstractJdbcAgentTest {
|
||||
private boolean autoCommit = true;
|
||||
private String compatibilityMode;
|
||||
private String identifierQuote = "\"";
|
||||
private String jdbcUrl;
|
||||
private boolean compatibilityQueryFails;
|
||||
private int compatibilityQueryCount;
|
||||
private boolean isValidUnsupported;
|
||||
@@ -534,6 +584,9 @@ class AbstractJdbcAgentTest {
|
||||
if ("getIdentifierQuoteString".equals(method.getName())) {
|
||||
return identifierQuote;
|
||||
}
|
||||
if ("getURL".equals(method.getName())) {
|
||||
return jdbcUrl;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user