Skip to content

Commit 8e6e1f9

Browse files
committed
db.query.summary multiple targets
1 parent a79b44c commit 8e6e1f9

File tree

2 files changed

+45
-15
lines changed

2 files changed

+45
-15
lines changed

instrumentation-api-incubator/src/main/jflex/SqlSanitizer.jflex

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ WHITESPACE = [ \t\r\n]+
7979
}
8080

8181
private void appendOperationToSummary(String operation) {
82-
// Avoid duplicate entries when subqueries have same operation
83-
if (operation != null && !operation.equals(lastQuerySummaryItem)) {
82+
if (operation != null) {
8483
if (querySummaryBuilder.length() > 0) {
8584
querySummaryBuilder.append(' ');
8685
}
@@ -139,6 +138,10 @@ WHITESPACE = [ \t\r\n]+
139138
private boolean insideComment = false;
140139
private Operation operation = NoOp.INSTANCE;
141140
private boolean extractionDone = false;
141+
// Tracks how many SELECT keywords we've seen (to track targets for subqueries)
142+
private int selectCount = 0;
143+
// Tracks whether we're expecting the next identifier after FROM for a subsequent SELECT's query summary
144+
private boolean expectingTargetForSubsequentSelect = false;
142145
private SqlDialect dialect;
143146

144147
private void setOperation(Operation operation) {
@@ -147,6 +150,24 @@ WHITESPACE = [ \t\r\n]+
147150
}
148151
}
149152

153+
// Called when we see FROM and have a subsequent SELECT pending
154+
private void handleFromForSubsequentSelect() {
155+
// Capture target for subsequent SELECTs:
156+
// - selectCount > 1: nested SELECT (e.g., SELECT FROM (SELECT FROM orders))
157+
// - selectCount >= 1 && extractionDone: SELECT after main operation done (e.g., INSERT INTO t SELECT FROM orders)
158+
if (selectCount > 1 || (selectCount >= 1 && extractionDone)) {
159+
expectingTargetForSubsequentSelect = true;
160+
}
161+
}
162+
163+
// Called when we capture a target after FROM for subsequent SELECT's query summary
164+
private void handleTargetForSubsequentSelect(String target) {
165+
if (expectingTargetForSubsequentSelect && target != null) {
166+
appendTargetToSummary(target);
167+
expectingTargetForSubsequentSelect = false;
168+
}
169+
}
170+
150171
private static abstract class Operation {
151172
String mainIdentifier = null;
152173

@@ -412,6 +433,7 @@ WHITESPACE = [ \t\r\n]+
412433
if (!insideComment) {
413434
setOperation(new Select());
414435
appendOperationToSummary("SELECT");
436+
selectCount++;
415437
}
416438
appendCurrentFragment();
417439
if (isOverLimit()) return YYEOF;
@@ -481,13 +503,17 @@ WHITESPACE = [ \t\r\n]+
481503
if (isOverLimit()) return YYEOF;
482504
}
483505
"FROM" {
484-
if (!insideComment && !extractionDone) {
485-
if (operation == NoOp.INSTANCE) {
486-
// hql/jpql queries may skip SELECT and start with FROM clause
487-
// treat such queries as SELECT queries
488-
setOperation(new Select());
506+
if (!insideComment) {
507+
if (!extractionDone) {
508+
if (operation == NoOp.INSTANCE) {
509+
// hql/jpql queries may skip SELECT and start with FROM clause
510+
// treat such queries as SELECT queries
511+
setOperation(new Select());
512+
}
513+
extractionDone = operation.handleFrom();
489514
}
490-
extractionDone = operation.handleFrom();
515+
// For subsequent SELECTs (nested or after INSERT), prepare to capture target
516+
handleFromForSubsequentSelect();
491517
}
492518
appendCurrentFragment();
493519
if (isOverLimit()) return YYEOF;
@@ -537,8 +563,13 @@ WHITESPACE = [ \t\r\n]+
537563
if (isOverLimit()) return YYEOF;
538564
}
539565
{IDENTIFIER} {
540-
if (!insideComment && !extractionDone) {
541-
extractionDone = operation.handleIdentifier();
566+
if (!insideComment) {
567+
if (!extractionDone) {
568+
extractionDone = operation.handleIdentifier();
569+
} else {
570+
// For subsequent SELECTs (e.g., SELECT in INSERT...SELECT), capture target for summary
571+
handleTargetForSubsequentSelect(readIdentifierName());
572+
}
542573
}
543574
appendCurrentFragment();
544575
if (isOverLimit()) return YYEOF;

instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlStatementSanitizerTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,18 @@ private static Stream<Arguments> querySummaryArgs() {
188188
// Basic SELECT
189189
Arguments.of("SELECT * FROM wuser_table", "SELECT wuser_table"),
190190
Arguments.of("SELECT * FROM wuser_table WHERE username = ?", "SELECT wuser_table"),
191-
// INSERT with SELECT subquery - INSERT target + SELECT operation (SELECT target not tracked
192-
// after extraction done)
191+
// INSERT with SELECT subquery - INSERT target + SELECT operation + SELECT target
193192
Arguments.of(
194193
"INSERT INTO shipping_details (order_id, address) SELECT order_id, address FROM orders WHERE order_id = ?",
195-
"INSERT shipping_details SELECT"),
194+
"INSERT shipping_details SELECT orders"),
196195
// SELECT with multiple tables (implicit join) - only first table tracked since extraction
197196
// stops on comma
198197
Arguments.of(
199198
"SELECT * FROM songs, artists WHERE songs.artist_id == artists.id", "SELECT songs"),
200-
// SELECT with subquery in FROM - only SELECT operation, no table from subquery
199+
// SELECT with subquery in FROM - outer SELECT + inner SELECT + inner table
201200
Arguments.of(
202201
"SELECT order_date FROM (SELECT * FROM orders o JOIN customers c ON o.customer_id = c.customer_id)",
203-
"SELECT"),
202+
"SELECT SELECT orders"),
204203
// SELECT with JOIN - first table tracked, extraction stops on JOIN
205204
Arguments.of("SELECT * FROM table1 JOIN table2 ON table1.id = table2.id", "SELECT table1"),
206205
// DELETE

0 commit comments

Comments
 (0)