>From Janhavi Tripurwar <[email protected]>:

Janhavi Tripurwar has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21619?usp=email )


Change subject: [ASTERIXDB-3593]Fix multi-statement response indentation
......................................................................

[ASTERIXDB-3593]Fix multi-statement response indentation

Ext-ref: MB-62708

Co-Authored-By: Claude Opus 5 <[email protected]>
Change-Id: I2cc80e82b2f93fc2feab1c0ba4491773e12414b6
---
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/NcStatementsPrinter.java
1 file changed, 73 insertions(+), 10 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/19/21619/1

diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/NcStatementsPrinter.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/NcStatementsPrinter.java
index 73f9b02..abdeaea 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/NcStatementsPrinter.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/NcStatementsPrinter.java
@@ -18,7 +18,10 @@
  */
 package org.apache.asterix.app.result.fields;

+import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -69,6 +72,8 @@
     /** Indent of a statement object's fields, one level deeper than the array 
itself. */
     private static final String FIELD_INDENT = "\t\t\t";

+    private static final String NESTED_SHIFT = "\t\t";
+
     /** One field of a statement object. Collected so that the separators 
cannot be got wrong. */
     private interface FieldEmitter {
         void emit(PrintWriter pw) throws HyracksDataException;
@@ -136,32 +141,35 @@
         // a statement that returns rows describes them, as the flat response 
does; the signature is the default one
         // unless the client asked for a typed one, exactly as 
SignaturePrinter.newInstance decides for a request
         if (printSignature && resultSetInfo != null) {
-            fields.add((plans == null ? SignaturePrinter.INSTANCE : 
SignaturePrinter.newInstance(plans))::print);
+            IResponseFieldPrinter signature =
+                    plans == null ? SignaturePrinter.INSTANCE : 
SignaturePrinter.newInstance(plans);
+            fields.add(w -> printNested(w, signature));
         }
         if (resultSetInfo != null) {
             if (delivery == ResultDelivery.IMMEDIATE) {
                 fields.add(w -> printRows(w, rows, resultSetInfo, stats));
             } else if (delivery == ResultDelivery.DEFERRED) {
                 // a handle per statement, each naming that statement's own job
-                fields.add(new ResultHandlePrinter(sessionOutput,
-                        new ResultHandle(resultSetInfo.getJobId(), 
resultSetInfo.getResultSetId(), requestId))::print);
+                fields.add(w -> printNested(w, new 
ResultHandlePrinter(sessionOutput,
+                        new ResultHandle(resultSetInfo.getJobId(), 
resultSetInfo.getResultSetId(), requestId))));
             }
         }
         if (plans != null) {
-            fields.add(new PlansPrinter(plans, 
sessionOutput.config().getPlanFormat())::print);
+            fields.add(w -> printNested(w, new PlansPrinter(plans, 
sessionOutput.config().getPlanFormat())));
         }
         fields.add(w -> printField(w, StatusPrinter.FIELD_NAME,
                 quoted((failed ? ResultStatus.FATAL : 
ResultStatus.SUCCESS).str())));
         if (failed) {
-            fields.add(errorsPrinter(statement.getError())::print);
+            fields.add(w -> printNested(w, 
errorsPrinter(statement.getError())));
         }
         if (!statement.getWarnings().isEmpty()) {
-            fields.add(warningsPrinter(statement.getWarnings())::print);
+            fields.add(w -> printNested(w, 
warningsPrinter(statement.getWarnings())));
         }
         // built when the field is printed, not now: the row count and size 
are only final once the rows are streamed
-        fields.add(w -> new MetricsPrinter(statementMetrics(stats, failed), 
resultCharset, STATEMENT_METRICS).print(w));
+        fields.add(w -> printNested(w,
+                new MetricsPrinter(statementMetrics(stats, failed), 
resultCharset, STATEMENT_METRICS)));
         if (stats.getJobProfile() != null) {
-            fields.add(new ProfilePrinter(stats.getJobProfile())::print);
+            fields.add(w -> printNested(w, new 
ProfilePrinter(stats.getJobProfile())));
         }

         if (separatorBefore) {
@@ -186,9 +194,64 @@
         pw.print(FIELD_INDENT);
         pw.print(quoted(ResultsPrinter.FIELD_NAME));
         pw.print(": ");
+        PrintWriter rows = new PrintWriter(new TrailingNewlineHolder(pw));
         // no result decorators: this printer names the field itself, so the 
decorators that name and number it must not
-        SessionOutput undecorated = new SessionOutput(sessionOutput.config(), 
pw);
-        ResultUtil.printResults(appCtx, reader, undecorated, stats, 
resultSetInfo.getRecordType());
+        SessionOutput undecorated = new SessionOutput(sessionOutput.config(), 
rows);
+        try {
+            ResultUtil.printResults(appCtx, reader, undecorated, stats, 
resultSetInfo.getRecordType());
+        } finally {
+            rows.flush();
+        }
+    }
+
+    private static final class TrailingNewlineHolder extends Writer {
+
+        private final Writer out;
+        private final StringBuilder held = new StringBuilder();
+
+        TrailingNewlineHolder(Writer out) {
+            this.out = out;
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            int end = off + len;
+            int contentEnd = end;
+            while (contentEnd > off && isLineBreak(cbuf[contentEnd - 1])) {
+                contentEnd--;
+            }
+            if (contentEnd > off) {
+                if (held.length() > 0) {
+                    out.write(held.toString());
+                    held.setLength(0);
+                }
+                out.write(cbuf, off, contentEnd - off);
+            }
+            held.append(cbuf, contentEnd, end - contentEnd);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            out.flush();
+        }
+
+        @Override
+        public void close() throws IOException {
+            flush();
+        }
+
+        private static boolean isLineBreak(char c) {
+            return c == '\n' || c == '\r';
+        }
+    }
+
+    private static void printNested(PrintWriter pw, IResponseFieldPrinter 
printer) throws HyracksDataException {
+        StringWriter buffer = new StringWriter();
+        PrintWriter bufferedWriter = new PrintWriter(buffer);
+        printer.print(bufferedWriter);
+        bufferedWriter.flush();
+        pw.print(NESTED_SHIFT);
+        pw.print(buffer.toString().replace("\n", "\n" + NESTED_SHIFT));
     }

     /** The errors of a failed statement. Overridable for a deployment that 
represents errors in its own form. */

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21619?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: I2cc80e82b2f93fc2feab1c0ba4491773e12414b6
Gerrit-Change-Number: 21619
Gerrit-PatchSet: 1
Gerrit-Owner: Janhavi Tripurwar <[email protected]>

Reply via email to