Browse Source

HUE-7277 [autocomplete] Fix issue where columns are marked as tables in the select list when qualified table references are used

Johan Ahlen 8 years ago
parent
commit
4859831b6c

+ 5 - 1
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_main.jison

@@ -1014,10 +1014,14 @@ BasicIdentifierChain
  : ColumnIdentifier
  : ColumnIdentifier
    {
    {
      $$ = [$1];
      $$ = [$1];
-     parser.addUnknownLocation(@1, [$1]);
+     parser.yy.firstChainLocation = parser.addUnknownLocation(@1, [$1]);
    }
    }
  | BasicIdentifierChain AnyDot ColumnIdentifier
  | BasicIdentifierChain AnyDot ColumnIdentifier
    {
    {
+     if (parser.yy.firstChainLocation) {
+       parser.yy.firstChainLocation.firstInChain = true;
+       delete parser.yy.firstChainLocation;
+     }
      $1.push($3);
      $1.push($3);
      parser.addUnknownLocation(@3, $1.concat());
      parser.addUnknownLocation(@3, $1.concat());
    }
    }

+ 67 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpecLocations.js

@@ -69,6 +69,73 @@
       });
       });
     });
     });
 
 
+    it('should report locations for "SELECT tbl FROM db.tbl; |"', function() {
+      assertLocations({
+        beforeCursor: 'SELECT tbl FROM db.tbl; ',
+        dialect: 'impala',
+        expectedLocations: [
+          { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 23 } },
+          { type: 'selectList', missing: false, location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11 } },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11 }, identifierChain: [ { name: 'tbl' }], tables: [{ identifierChain: [{ name: 'db' }, { name: 'tbl' }] }] },
+          { type: 'database', location: { first_line: 1, last_line: 1, first_column: 17, last_column: 19 }, identifierChain: [{ name: 'db' }] },
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 20, last_column: 23 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 23, last_column: 23 } },
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 23, last_column: 23 } }
+        ]
+      });
+    });
+
+    it('should report locations for "SELECT tbl.col FROM db.tbl; |"', function() {
+      assertLocations({
+        beforeCursor: 'SELECT tbl.col FROM db.tbl; ',
+        dialect: 'impala',
+        expectedLocations: [
+          { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 27 } },
+          { type: 'selectList', missing: false, location: { first_line: 1, last_line: 1, first_column: 8, last_column: 15 } },
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 12, last_column: 15 }, identifierChain: [{ name: 'col' }], tables: [{ identifierChain: [{ name: 'db' }, { name: 'tbl' }] }] },
+          { type: 'database', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 23 }, identifierChain: [{ name: 'db' }] },
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 27 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 27, last_column: 27 } },
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 27, last_column: 27 } }
+        ]
+      });
+    });
+
+    it('should report locations for "SELECT a.col FROM db.tbl a; |"', function() {
+      assertLocations({
+        beforeCursor: 'SELECT a.col FROM db.tbl a; ',
+        expectedLocations: [
+          { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 27 } },
+          { type: 'selectList', missing: false, location: { first_line: 1, last_line: 1, first_column: 8, last_column: 13 } },
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 10, last_column: 13 }, identifierChain: [{ name: 'col' }], tables: [{ identifierChain: [{ name: 'db' }, { name: 'tbl' }], alias: 'a' }] },
+          { type: 'database', location: { first_line: 1, last_line: 1, first_column: 19, last_column: 21 }, identifierChain: [{ name: 'db' }] },
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 22, last_column: 25 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'alias', source: 'table', alias: 'a', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 27 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 27, last_column: 27 } },
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 27, last_column: 27 } }
+        ]
+      });
+    });
+
+    it('should report locations for "SELECT tbl.col FROM db.tbl a; |"', function() {
+      assertLocations({
+        beforeCursor: 'SELECT tbl.col FROM db.tbl a; ',
+        expectedLocations: [
+          { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 29 } },
+          { type: 'selectList', missing: false, location: { first_line: 1, last_line: 1, first_column: 8, last_column: 15 } },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11 }, identifierChain: [{ name: 'tbl' }], tables: [{ identifierChain: [{ name: 'db' }, { name: 'tbl' }], alias: 'a' }] },
+          { type: 'complex', location: { first_line: 1, last_line: 1, first_column: 12, last_column: 15 }, identifierChain: [{ name: 'tbl' }, { name: 'col' }], tables: [{ identifierChain: [{ name: 'db' }, { name: 'tbl' }], alias: 'a' }] },
+          { type: 'database', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 23 }, identifierChain: [{ name: 'db' }] },
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 27 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'alias', source: 'table', alias: 'a', location: { first_line: 1, last_line: 1, first_column: 28, last_column: 29 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 29, last_column: 29 } },
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 29, last_column: 29 } }
+        ]
+      });
+    });
+
     it('should report locations for "select x from x;"', function () {
     it('should report locations for "select x from x;"', function () {
       assertLocations({
       assertLocations({
         beforeCursor: 'select x from x;',
         beforeCursor: 'select x from x;',

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlAutocompleteParser.js


+ 18 - 4
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlParseSupport.js

@@ -394,7 +394,13 @@ var SqlParseSupport = (function () {
             var found = parser.yy.latestTablePrimaries.filter(function (primary) {
             var found = parser.yy.latestTablePrimaries.filter(function (primary) {
               return equalIgnoreCase(primary.alias, location.identifierChain[0].name) || (primary.identifierChain && equalIgnoreCase(primary.identifierChain[0].name, location.identifierChain[0].name));
               return equalIgnoreCase(primary.alias, location.identifierChain[0].name) || (primary.identifierChain && equalIgnoreCase(primary.identifierChain[0].name, location.identifierChain[0].name));
             });
             });
-            if (found.length > 0) {
+            if (!found.length && location.firstInChain) {
+              found = parser.yy.latestTablePrimaries.filter(function (primary) {
+                return !primary.alias && primary.identifierChain && equalIgnoreCase(primary.identifierChain[primary.identifierChain.length - 1].name, location.identifierChain[0].name);
+              });
+            }
+
+            if (found.length) {
               if (found[0].identifierChain.length > 1 && location.identifierChain.length === 1 && equalIgnoreCase(found[0].identifierChain[0].name, location.identifierChain[0].name)) {
               if (found[0].identifierChain.length > 1 && location.identifierChain.length === 1 && equalIgnoreCase(found[0].identifierChain[0].name, location.identifierChain[0].name)) {
                 location.type = 'database';
                 location.type = 'database';
               } else if (found[0].alias && equalIgnoreCase(location.identifierChain[0].name, found[0].alias) && location.identifierChain.length > 1) {
               } else if (found[0].alias && equalIgnoreCase(location.identifierChain[0].name, found[0].alias) && location.identifierChain.length > 1) {
@@ -445,10 +451,15 @@ var SqlParseSupport = (function () {
           if (parser.isHive() && !location.linked) {
           if (parser.isHive() && !location.linked) {
             location.identifierChain = parser.expandLateralViews(parser.yy.lateralViews, location.identifierChain);
             location.identifierChain = parser.expandLateralViews(parser.yy.lateralViews, location.identifierChain);
           }
           }
+
+          var initialIdentifierChain = location.identifierChain ? location.identifierChain.concat() : undefined;
           parser.expandIdentifierChain(location, true, true, true);
           parser.expandIdentifierChain(location, true, true, true);
 
 
           if (typeof location.identifierChain === 'undefined') {
           if (typeof location.identifierChain === 'undefined') {
             parser.yy.locations.splice(i, 1);
             parser.yy.locations.splice(i, 1);
+          } else if (location.identifierChain.length === 0 && initialIdentifierChain && initialIdentifierChain.length === 1) {
+            // This is for the case "SELECT tblOrColName FROM db.tblOrColName";
+            location.identifierChain = initialIdentifierChain;
           }
           }
         }
         }
         if (location.type === 'column' && location.identifierChain) {
         if (location.type === 'column' && location.identifierChain) {
@@ -456,6 +467,7 @@ var SqlParseSupport = (function () {
             location.type = 'complex';
             location.type = 'complex';
           }
           }
         }
         }
+        delete location.firstInChain;
       }
       }
       if (parser.yy.locations.length > 0) {
       if (parser.yy.locations.length > 0) {
         parser.yy.allLocations = parser.yy.allLocations.concat(parser.yy.locations);
         parser.yy.allLocations = parser.yy.allLocations.concat(parser.yy.locations);
@@ -781,7 +793,7 @@ var SqlParseSupport = (function () {
           } else if (!foundPrimary && equalIgnoreCase(tablePrimaries[i].identifierChain[0].name, identifierChain[0].name) && identifierChain.length > (isColumnLocation ? 1 : 0)) {
           } else if (!foundPrimary && equalIgnoreCase(tablePrimaries[i].identifierChain[0].name, identifierChain[0].name) && identifierChain.length > (isColumnLocation ? 1 : 0)) {
             foundPrimary = tablePrimaries[i];
             foundPrimary = tablePrimaries[i];
             // No break as first two can still match.
             // No break as first two can still match.
-          } else if (!foundPrimary && tablePrimaries[i].identifierChain.length > 1
+          } else if (!foundPrimary && tablePrimaries[i].identifierChain.length > 1 && !tablePrimaries[i].alias
             && equalIgnoreCase(tablePrimaries[i].identifierChain[tablePrimaries[i].identifierChain.length - 1].name, identifierChain[0].name)) {
             && equalIgnoreCase(tablePrimaries[i].identifierChain[tablePrimaries[i].identifierChain.length - 1].name, identifierChain[0].name)) {
             // This is for the case SELECT baa. FROM bla.baa, blo.boo;
             // This is for the case SELECT baa. FROM bla.baa, blo.boo;
             foundPrimary = tablePrimaries[i];
             foundPrimary = tablePrimaries[i];
@@ -1392,11 +1404,13 @@ var SqlParseSupport = (function () {
     };
     };
 
 
     parser.addUnknownLocation = function (location, identifierChain) {
     parser.addUnknownLocation = function (location, identifierChain) {
-      parser.yy.locations.push({
+      var unknownLoc = {
         type: 'unknown',
         type: 'unknown',
         location: adjustLocationForCursor(location),
         location: adjustLocationForCursor(location),
         identifierChain: identifierChain
         identifierChain: identifierChain
-      });
+      };
+      parser.yy.locations.push(unknownLoc);
+      return unknownLoc;
     };
     };
 
 
     parser.suggestDatabases = function (details) {
     parser.suggestDatabases = function (details) {

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlSyntaxParser.js


Some files were not shown because too many files changed in this diff