Skip to content

Commit 256a096

Browse files
authored
fix JDBC's SQLCommenter not taking into account semicolons (#9915)
* fix JDBC's SQLCommenter not taking into account semicolons After adding the new always append comment feature in #9798, a customer found a bug that was present in our SQL Commenter since a long time. Basically, JDBC always split queries to send to the DB on the semicolon. If a comment is after a semicolon, JDBC will still split the queries, and return multiple ResultSet. This provoked exceptions like this one: ``` org.postgresql.util.PSQLException: Multiple ResultSets were returned by the query ``` SDBM-2100 * replace query trimming with manual iteration over query in SQL Commenter * improve performance of the detection of semicolon in the SQL commenter
1 parent d533e9e commit 256a096

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/SQLCommenter.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,16 @@ public static String inject(
102102
Config config = Config.get();
103103

104104
StringBuilder sb = new StringBuilder(sql.length() + INJECTED_COMMENT_ESTIMATED_SIZE);
105+
int closingSemicolonIndex = indexOfClosingSemicolon(sql);
105106
if (appendComment) {
106-
sb.append(sql);
107+
if (closingSemicolonIndex > -1) {
108+
sb.append(sql, 0, closingSemicolonIndex);
109+
} else {
110+
sb.append(sql);
111+
}
107112
sb.append(SPACE);
108113
}
114+
109115
sb.append(OPEN_COMMENT);
110116
int initSize = sb.length();
111117
append(sb, PARENT_SERVICE, config.getServiceName(), initSize);
@@ -128,6 +134,11 @@ public static String inject(
128134
sb.append(SPACE);
129135
sb.append(sql);
130136
}
137+
138+
if (appendComment && closingSemicolonIndex > -1) {
139+
sb.append(';');
140+
}
141+
131142
return sb.toString();
132143
}
133144

@@ -198,4 +209,23 @@ private static void append(StringBuilder sb, String key, String value, int initS
198209
}
199210
sb.append(key).append(EQUALS).append(QUOTE).append(encodedValue).append(QUOTE);
200211
}
212+
213+
/**
214+
* @param query SQL query
215+
* @return index of the semicolon that ends the query, or -1 if none
216+
*/
217+
private static int indexOfClosingSemicolon(String query) {
218+
for (int i = query.length() - 1; i >= 0; i--) {
219+
char c = query.charAt(i);
220+
if (c == ';') {
221+
return i;
222+
} else if (Character.isWhitespace(c)) {
223+
continue;
224+
}
225+
226+
break;
227+
}
228+
229+
return -1;
230+
}
201231
}

dd-java-agent/instrumentation/jdbc/src/test/groovy/SQLCommenterTest.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ class SQLCommenterTest extends InstrumentationSpecification {
4747
where:
4848
query | ddService | ddEnv | dbService | dbType | host | dbName | ddVersion | append | traceParent | expected
4949
"SELECT * FROM foo" | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "SELECT * FROM foo /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/"
50+
"SELECT * FROM foo;" | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "SELECT * FROM foo /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/;"
51+
"SELECT * FROM foo; \t\n\r" | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "SELECT * FROM foo /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/;"
52+
"SELECT * FROM foo; SELECT * FROM bar" | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "SELECT * FROM foo; SELECT * FROM bar /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/"
53+
"SELECT * FROM foo; SELECT * FROM bar; " | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "SELECT * FROM foo; SELECT * FROM bar /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/;"
5054
"SELECT * FROM foo" | "SqlCommenter" | "Test" | "my-service" | "postgres" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "SELECT * FROM foo /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/"
5155
"{call dogshelterProc(?, ?)}" | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | true | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "{call dogshelterProc(?, ?)} /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/"
5256
"{call dogshelterProc(?, ?)}" | "SqlCommenter" | "Test" | "my-service" | "mysql" | "h" | "n" | "TestVersion" | false | "00-00000000000000007fffffffffffffff-000000024cb016ea-00" | "{call dogshelterProc(?, ?)} /*ddps='SqlCommenter',dddbs='my-service',ddh='h',dddb='n',dde='Test',ddpv='TestVersion',traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-00'*/"

0 commit comments

Comments
 (0)