@@ -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 ;
0 commit comments