You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by vo...@apache.org on 2022/09/17 21:02:54 UTC

[druid] branch master updated: Web console: correctly escape path based flatten specs (#13105)

This is an automated email from the ASF dual-hosted git repository.

vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new de8f229bed Web console: correctly escape path based flatten specs (#13105)
de8f229bed is described below

commit de8f229bed6624b2b4fca493ff4a9e8ca04c0fb1
Author: Vadim Ogievetsky <va...@ogievetsky.com>
AuthorDate: Sat Sep 17 14:02:42 2022 -0700

    Web console: correctly escape path based flatten specs (#13105)
    
    * fix path generation
    
    * do escape
    
    * fix replace
    
    * fix replace for good
---
 .../druid-models/flatten-spec/flatten-spec.spec.ts | 24 +++++++---------------
 .../src/druid-models/flatten-spec/flatten-spec.tsx | 24 ++++++++++------------
 .../src/views/load-data-view/load-data-view.tsx    |  1 -
 .../result-table-pane/result-table-pane.tsx        |  2 +-
 4 files changed, 19 insertions(+), 32 deletions(-)

diff --git a/web-console/src/druid-models/flatten-spec/flatten-spec.spec.ts b/web-console/src/druid-models/flatten-spec/flatten-spec.spec.ts
index a35c185381..822dd48eba 100644
--- a/web-console/src/druid-models/flatten-spec/flatten-spec.spec.ts
+++ b/web-console/src/druid-models/flatten-spec/flatten-spec.spec.ts
@@ -22,7 +22,7 @@ describe('flatten-spec', () => {
   describe('computeFlattenExprsForData', () => {
     const data = [
       {
-        context: { host: 'cla', topic: 'moon', bonus: { foo: 'bar' } },
+        context: { host: 'cla', topic: 'moon', bonus: { 'fo.o': 'bar' } },
         tags: ['a', 'b', 'c'],
         messages: [
           { metric: 'request/time', value: 122 },
@@ -32,7 +32,7 @@ describe('flatten-spec', () => {
         value: 5,
       },
       {
-        context: { host: 'piv', popic: 'sun' },
+        context: { 'host': 'piv', '1pic': 'sun' },
         tags: ['a', 'd'],
         messages: [
           { metric: 'request/time', value: 44 },
@@ -41,7 +41,7 @@ describe('flatten-spec', () => {
         value: 4,
       },
       {
-        context: { host: 'imp', dopik: 'fun' },
+        context: { 'host': 'imp', "d\\o\npi'c'": 'fun' },
         tags: ['x', 'y'],
         messages: [
           { metric: 'request/time', value: 4 },
@@ -53,22 +53,12 @@ describe('flatten-spec', () => {
     ];
 
     it('works for path, ignore-arrays', () => {
-      expect(computeFlattenExprsForData(data, 'path', 'ignore-arrays')).toEqual([
-        '$.context.bonus.foo',
-        '$.context.dopik',
+      expect(computeFlattenExprsForData(data, 'ignore-arrays')).toEqual([
+        "$.context.bonus['fo.o']",
         '$.context.host',
-        '$.context.popic',
         '$.context.topic',
-      ]);
-    });
-
-    it('works for jq, ignore-arrays', () => {
-      expect(computeFlattenExprsForData(data, 'jq', 'ignore-arrays')).toEqual([
-        '.context.bonus.foo',
-        '.context.dopik',
-        '.context.host',
-        '.context.popic',
-        '.context.topic',
+        "$.context['1pic']",
+        "$.context['d\\\\o\npi\\'c\\'']",
       ]);
     });
   });
diff --git a/web-console/src/druid-models/flatten-spec/flatten-spec.tsx b/web-console/src/druid-models/flatten-spec/flatten-spec.tsx
index 3845a83916..5cf1d7c06c 100644
--- a/web-console/src/druid-models/flatten-spec/flatten-spec.tsx
+++ b/web-console/src/druid-models/flatten-spec/flatten-spec.tsx
@@ -61,18 +61,22 @@ export const FLATTEN_FIELD_FIELDS: Field<FlattenField>[] = [
   },
 ];
 
-export type ExprType = 'path' | 'jq';
 export type ArrayHandling = 'ignore-arrays' | 'include-arrays';
 
+function escapePathKey(pathKey: string): string {
+  return /^[a-z]\w*$/i.test(pathKey)
+    ? `.${pathKey}`
+    : `['${pathKey.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}']`;
+}
+
 export function computeFlattenPathsForData(
   data: Record<string, any>[],
-  exprType: ExprType,
   arrayHandling: ArrayHandling,
 ): FlattenField[] {
-  return computeFlattenExprsForData(data, exprType, arrayHandling).map(expr => {
+  return computeFlattenExprsForData(data, arrayHandling).map(expr => {
     return {
-      name: expr.replace(/^\$?\./, ''),
-      type: exprType,
+      name: expr.replace(/^\$\./, '').replace(/['\]]/g, '').replace(/\[/g, '.'),
+      type: 'path',
       expr,
     };
   });
@@ -80,7 +84,6 @@ export function computeFlattenPathsForData(
 
 export function computeFlattenExprsForData(
   data: Record<string, any>[],
-  exprType: ExprType,
   arrayHandling: ArrayHandling,
   includeTopLevel = false,
 ): string[] {
@@ -91,12 +94,7 @@ export function computeFlattenExprsForData(
     for (const datumKey of datumKeys) {
       const datumValue = datum[datumKey];
       if (includeTopLevel || isNested(datumValue)) {
-        addPath(
-          seenPaths,
-          exprType === 'path' ? `$.${datumKey}` : `.${datumKey}`,
-          datumValue,
-          arrayHandling,
-        );
+        addPath(seenPaths, `$${escapePathKey(datumKey)}`, datumValue, arrayHandling);
       }
     }
   }
@@ -114,7 +112,7 @@ function addPath(
     if (!Array.isArray(value)) {
       const valueKeys = Object.keys(value);
       for (const valueKey of valueKeys) {
-        addPath(paths, `${path}.${valueKey}`, value[valueKey], arrayHandling);
+        addPath(paths, `${path}${escapePathKey(valueKey)}`, value[valueKey], arrayHandling);
       }
     } else if (arrayHandling === 'include-arrays') {
       for (let i = 0; i < value.length; i++) {
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index 7afc13aa75..989263a880 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -1490,7 +1490,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     if (canFlatten && !flattenFields.length && parserQueryState.data) {
       suggestedFlattenFields = computeFlattenPathsForData(
         filterMap(parserQueryState.data.rows, r => r.input),
-        'path',
         'ignore-arrays',
       );
     }
diff --git a/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx b/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx
index e4b78b5af7..ba8b11001a 100644
--- a/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx
+++ b/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx
@@ -82,7 +82,7 @@ function jsonValue(ex: SqlExpression, path: string): SqlExpression {
 }
 
 function getJsonPaths(jsons: Record<string, any>[]): string[] {
-  return ['$.'].concat(computeFlattenExprsForData(jsons, 'path', 'include-arrays', true));
+  return ['$.'].concat(computeFlattenExprsForData(jsons, 'include-arrays', true));
 }
 
 function isComparable(x: unknown): boolean {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org