|
@@ -5,8 +5,10 @@
|
|
|
*/
|
|
|
package org.elasticsearch.xpack.sql.plugin;
|
|
|
|
|
|
+import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.common.Strings;
|
|
|
import org.elasticsearch.rest.RestRequest;
|
|
|
+import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
|
|
import org.elasticsearch.xpack.sql.action.BasicFormatter;
|
|
|
import org.elasticsearch.xpack.sql.action.SqlQueryResponse;
|
|
|
import org.elasticsearch.xpack.sql.proto.ColumnInfo;
|
|
@@ -26,9 +28,6 @@ import static org.elasticsearch.xpack.sql.action.BasicFormatter.FormatOption.TEX
|
|
|
/**
|
|
|
* Templating class for displaying SQL responses in text formats.
|
|
|
*/
|
|
|
-
|
|
|
-// TODO are we sure toString is correct here? What about dates that come back as longs.
|
|
|
-// Tracked by https://github.com/elastic/x-pack-elasticsearch/issues/3081
|
|
|
enum TextFormat {
|
|
|
|
|
|
/**
|
|
@@ -41,22 +40,38 @@ enum TextFormat {
|
|
|
*/
|
|
|
PLAIN_TEXT() {
|
|
|
@Override
|
|
|
- String format(Cursor cursor, RestRequest request, SqlQueryResponse response) {
|
|
|
- final BasicFormatter formatter;
|
|
|
- if (cursor instanceof TextFormatterCursor) {
|
|
|
- formatter = ((TextFormatterCursor) cursor).getFormatter();
|
|
|
- return formatter.formatWithoutHeader(response.rows());
|
|
|
- } else {
|
|
|
+ String format(RestRequest request, SqlQueryResponse response) {
|
|
|
+ BasicFormatter formatter = null;
|
|
|
+ Cursor cursor = null;
|
|
|
+
|
|
|
+ // check if the cursor is already wrapped first
|
|
|
+ if (response.hasCursor()) {
|
|
|
+ cursor = Cursors.decodeFromString(response.cursor());
|
|
|
+ if (cursor instanceof TextFormatterCursor) {
|
|
|
+ formatter = ((TextFormatterCursor) cursor).getFormatter();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // if there are headers available, it means it's the first request
|
|
|
+ // so initialize the underlying formatter and wrap it in the cursor
|
|
|
+ if (response.columns() != null) {
|
|
|
formatter = new BasicFormatter(response.columns(), response.rows(), TEXT);
|
|
|
+ // if there's a cursor, wrap the formatter in it
|
|
|
+ if (cursor != null) {
|
|
|
+ response.cursor(Cursors.encodeToString(Version.CURRENT, new TextFormatterCursor(cursor, formatter)));
|
|
|
+ }
|
|
|
+ // format with header
|
|
|
return formatter.formatWithHeader(response.columns(), response.rows());
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- Cursor wrapCursor(Cursor oldCursor, SqlQueryResponse response) {
|
|
|
- BasicFormatter formatter = (oldCursor instanceof TextFormatterCursor) ?
|
|
|
- ((TextFormatterCursor) oldCursor).getFormatter() : new BasicFormatter(response.columns(), response.rows(), TEXT);
|
|
|
- return TextFormatterCursor.wrap(super.wrapCursor(oldCursor, response), formatter);
|
|
|
+ else {
|
|
|
+ // should be initialized (wrapped by the cursor)
|
|
|
+ if (formatter != null) {
|
|
|
+ // format without header
|
|
|
+ return formatter.formatWithoutHeader(response.rows());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // if this code is reached, it means it's a next page without cursor wrapping
|
|
|
+ throw new SqlIllegalArgumentException("Cannot find text formatter - this is likely a bug");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -219,12 +234,11 @@ enum TextFormat {
|
|
|
};
|
|
|
|
|
|
|
|
|
- String format(Cursor cursor, RestRequest request, SqlQueryResponse response) {
|
|
|
+ String format(RestRequest request, SqlQueryResponse response) {
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
- boolean header = hasHeader(request);
|
|
|
-
|
|
|
- if (header && (cursor == null || cursor == Cursor.EMPTY)) {
|
|
|
+ // if the header is requested (and the column info is present - namely it's the first page) return the info
|
|
|
+ if (hasHeader(request) && response.columns() != null) {
|
|
|
row(sb, response.columns(), ColumnInfo::name);
|
|
|
}
|
|
|
|
|
@@ -239,10 +253,6 @@ enum TextFormat {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- Cursor wrapCursor(Cursor oldCursor, SqlQueryResponse response) {
|
|
|
- return Cursors.decodeFromString(response.cursor());
|
|
|
- }
|
|
|
-
|
|
|
static TextFormat fromMediaTypeOrFormat(String accept) {
|
|
|
for (TextFormat text : values()) {
|
|
|
String contentType = text.contentType();
|