فهرست منبع

HUE-6976 [autocomplete] Report locations for WHERE and LIMIT clauses

This adjusts the parser to report locations for filters and limits, if they're not specified it will instead report the expected locations.
Johan Ahlen 8 سال پیش
والد
کامیت
55efd6b

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

@@ -1483,14 +1483,25 @@ OptionalAllOrDistinct
 
 TableExpression
  : FromClause OptionalSelectConditions
+   {
+     parser.addClauseLocation('whereClause', @1, $2.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+   }
  ;
 
 TableExpression_EDIT
  : FromClause_EDIT OptionalSelectConditions
+   {
+     parser.addClauseLocation('whereClause', @1, $2.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+   }
  | FromClause 'CURSOR' OptionalSelectConditions OptionalJoins
    {
      var keywords = [];
 
+     parser.addClauseLocation('whereClause', @1, $3.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+
      if ($1) {
        if (!$1.hasLateralViews && typeof $1.tableReferenceList.hasJoinCondition !== 'undefined' && !$1.tableReferenceList.hasJoinCondition) {
          keywords.push({ value: 'ON', weight: 3 });
@@ -1579,8 +1590,12 @@ TableExpression_EDIT
      //   or 'AND' based on type
 
      if (!$2) {
+       parser.addClauseLocation('whereClause', @1);
+       parser.addClauseLocation('limitClause', @1);
        return;
      }
+     parser.addClauseLocation('whereClause', @1, $2.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
      var keywords = [];
 
      if ($2.suggestColRefKeywords) {
@@ -1652,6 +1667,10 @@ OptionalSelectConditions
        $$ = {};
      }
 
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($6, @6, $5, @5, $4, @4, $3, @3, $2, @2, $1, @1);
+     $$.limitClauseLocation = $7 ? @7 : undefined;
+
      if (!$1 && !$2 && !$3 && !$4 && !$5 && !$6 && !$7 && !$8) {
        $$.suggestFilters = { prefix: 'WHERE', tablePrimaries: parser.yy.latestTablePrimaries.concat() };
      }
@@ -1711,6 +1730,9 @@ OptionalSelectConditions_EDIT
      if (!$3 && !$4 && !$5 && !$6) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($7, @7, $6, @6, $5, @5, $4, @4, $3, @3, $1, @1);
+     $$.limitClauseLocation = $8 ? @8 : undefined;
    }
  | OptionalWhereClause GroupByClause 'CURSOR' OptionalHavingClause OptionalWindowClause OptionalOrderByClause OptionalClusterOrDistributeBy OptionalLimitClause OptionalOffsetClause
    {
@@ -1729,6 +1751,9 @@ OptionalSelectConditions_EDIT
      if (!$4 && !$5 && !$6) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($7, @7, $6, @6, $5, @5, $4, @4, $2, @2);
+     $$.limitClauseLocation = $8 ? @8 : undefined;
    }
  | OptionalWhereClause OptionalGroupByClause HavingClause 'CURSOR' OptionalWindowClause OptionalOrderByClause OptionalClusterOrDistributeBy OptionalLimitClause OptionalOffsetClause
    {
@@ -1740,6 +1765,9 @@ OptionalSelectConditions_EDIT
      if (!$5 && !$6) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($7, @7, $6, @6, $5, @5, $3, @3);
+     $$.limitClauseLocation = $8 ? @8 : undefined;
    }
  | OptionalWhereClause OptionalGroupByClause OptionalHavingClause WindowClause 'CURSOR' OptionalOrderByClause OptionalClusterOrDistributeBy OptionalLimitClause OptionalOffsetClause
    {
@@ -1748,7 +1776,9 @@ OptionalSelectConditions_EDIT
      if (!$6) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
-
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($7, @7, $6, @6, $4, @4);
+     $$.limitClauseLocation = $8 ? @8 : undefined;
    }
  | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalWindowClause OrderByClause 'CURSOR' OptionalClusterOrDistributeBy OptionalLimitClause OptionalOffsetClause
    {
@@ -1757,6 +1787,9 @@ OptionalSelectConditions_EDIT
        keywords = keywords.concat(parser.createWeightedKeywords($5.suggestKeywords, 5));
      }
      $$ = { suggestKeywords: keywords, cursorAtEnd: !$7 && !$8 && !$9 };
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($7, @7, $5, @5);
+     $$.limitClauseLocation = $8 ? @8 : undefined;
    }
  | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalWindowClause OptionalOrderByClause ClusterOrDistributeBy 'CURSOR' OptionalLimitClause OptionalOffsetClause
    {
@@ -1765,11 +1798,17 @@ OptionalSelectConditions_EDIT
        keywords = keywords.concat(parser.createWeightedKeywords($6.suggestKeywords, 4));
      }
      $$ = { suggestKeywords: keywords, cursorAtEnd: !$8 && !$9 };
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = @6;
+     $$.limitClauseLocation = $8 ? @8 : undefined;
    }
  | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalWindowClause OptionalOrderByClause OptionalClusterOrDistributeBy LimitClause 'CURSOR' OptionalOffsetClause
    {
      var keywords = parser.getKeywordsForOptionalsLR([$9], [{ value: 'OFFSET', weight: 2 }], [parser.isImpala()]);
      $$ = { suggestKeywords: keywords, cursorAtEnd: !$9 };
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($6, @6, $5, @5, $4, @4, $3, @3, $2, @2, $1, @1);
+     $$.limitClauseLocation = $7 ? @7 : undefined;
    }
  ;
 

+ 6 - 2
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpec.js

@@ -440,7 +440,9 @@
           locations: [
             { type: 'statement', location: { first_line: 1, last_line: 2, first_column: 1, last_column: 25 } },
             { type: 'asterisk', location: { first_line: 2, last_line: 2, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'testTable1' }] }] },
-            { type: 'table', location: { first_line:2, last_line:2, first_column:15, last_column:25 }, identifierChain: [{ name: 'testTable1' }] }
+            { type: 'table', location: { first_line:2, last_line:2, first_column:15, last_column:25 }, identifierChain: [{ name: 'testTable1' }] },
+            { type: 'whereClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 25, last_column: 25 } },
+            { type: 'limitClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 25, last_column: 25 } }
           ],
           lowerCase: false
         }
@@ -456,7 +458,9 @@
           locations: [
             { type: 'statement', location: { first_line: 1, last_line: 4, first_column: 1, last_column: 25 } },
             { type: 'asterisk', location: { first_line: 4, last_line: 4, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'testTable1' }] }] },
-            { type: 'table', location: { first_line:4, last_line:4, first_column:15, last_column:25 }, identifierChain: [{ name: 'testTable1' }] }
+            { type: 'table', location: { first_line:4, last_line:4, first_column:15, last_column:25 }, identifierChain: [{ name: 'testTable1' }] },
+            { type: 'whereClause', missing: true, location: { first_line: 4, last_line: 4, first_column: 25, last_column: 25 } },
+            { type: 'limitClause', missing: true, location: { first_line: 4, last_line: 4, first_column: 25, last_column: 25 } }
           ],
           lowerCase: false
         }

+ 114 - 49
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpecLocations.js

@@ -43,7 +43,9 @@
           { type: 'asterisk', location: { first_line:1, last_line:1, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'testTable1' }] }, { identifierChain: [{ name: 'db1' }, { name: 'table2' }] }] },
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 25 }, identifierChain: [{ name: 'testTable1' }] },
           { type: 'database', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 34}, identifierChain: [{ name: 'db1' }]},
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 35, last_column: 41 }, identifierChain: [{ name: 'db1' }, { name: 'table2' }] }
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 35, last_column: 41 }, identifierChain: [{ name: 'db1' }, { name: 'table2' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 41, last_column: 41 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 41, last_column: 41 }}
         ]
       });
     });
@@ -58,7 +60,9 @@
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 11, last_column: 14 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }]},
           { type: 'column', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 18 }, identifierChain: [{ name: 'col'}], tables: [{ identifierChain: [{ name: 'db' }, { name: 'tbl' }]}]},
           { type: 'database', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 26 }, identifierChain: [{ name: 'db' }]},
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 27, last_column: 30 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }]}
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 27, last_column: 30 }, identifierChain: [{ name: 'db' }, { name: 'tbl' }]},
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 30, last_column: 30 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 30, last_column: 30 }}
         ]
       });
     });
@@ -69,7 +73,9 @@
         expectedLocations: [
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 16 } },
           { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, identifierChain: [{ name: 'x' }], tables: [{ identifierChain: [{ name: 'x' }] }]},
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'x' }]}
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'x' }]},
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 16, last_column: 16 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 16, last_column: 16 }}
         ]
       });
     });
@@ -81,9 +87,13 @@
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 16 } },
           { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, identifierChain: [{ name: 'x' }], tables: [{ identifierChain: [{ name: 'x' }] }] },
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'x' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 16, last_column: 16 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 16, last_column: 16 }},
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 17, last_column: 32 } },
           { type: 'column', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 25 }, identifierChain: [{ name: 'y' }], tables: [{ identifierChain: [{ name: 'y' }] }] },
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 32 }, identifierChain: [{ name: 'y' }] }
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 32 }, identifierChain: [{ name: 'y' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 32, last_column: 32 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 32, last_column: 32 }}
         ]
       });
     });
@@ -95,9 +105,13 @@
           { type: 'statement', location: { first_line: 1, last_line: 2, first_column: 1, last_column: 16 } },
           { type: 'column', location: { first_line: 2, last_line: 2, first_column: 8, last_column: 9 }, identifierChain: [{ name: 'x' }], tables: [{ identifierChain: [{ name: 'x' }] }] },
           { type: 'table', location: { first_line: 2, last_line: 2, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'x' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 16, last_column: 16 }},
+          { type: 'limitClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 16, last_column: 16 }},
           { type: 'statement', location: { first_line: 2, last_line: 5, first_column: 17, last_column: 16 } },
           { type: 'column', location: { first_line: 5, last_line: 5, first_column: 8, last_column: 9 }, identifierChain: [{ name: 'y' }], tables: [{ identifierChain: [{ name: 'y' }] }] },
-          { type: 'table', location: { first_line: 5, last_line: 5, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'y' }] }
+          { type: 'table', location: { first_line: 5, last_line: 5, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'y' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 5, last_line: 5, first_column: 16, last_column: 16 }},
+          { type: 'limitClause', missing: true, location: { first_line: 5, last_line: 5, first_column: 16, last_column: 16 }}
         ]
       });
     });
@@ -109,7 +123,9 @@
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 19 } },
           { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, identifierChain: [{ name: 'x' }], tables: [{ identifierChain: [{ name: 'x' }] }, { identifierChain: [{ name: 'y' }] }]},
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'x' }]},
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 18, last_column: 19 }, identifierChain: [{ name: 'y' }]}
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 18, last_column: 19 }, identifierChain: [{ name: 'y' }]},
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 19, last_column: 19 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 19, last_column: 19 }}
         ]
       });
     });
@@ -125,7 +141,9 @@
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 23, last_column: 33 }, identifierChain: [{ name: 'testTable1' }] },
           { type: 'database', location: { first_line: 1, last_line: 1, first_column: 35, last_column: 37 }, identifierChain: [{ name: 'db' }]},
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 38, last_column: 48 }, identifierChain: [{ name: 'db' },{ name: 'testTable2'}] },
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 50, last_column: 60 }, identifierChain: [{ name: 'testTable3' }] }
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 50, last_column: 60 }, identifierChain: [{ name: 'testTable3' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 63, last_column: 63 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 63, last_column: 63 }}
         ]
       });
     });
@@ -137,7 +155,9 @@
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 42 } },
           { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'foo' }] }] },
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 18 }, identifierChain: [{ name: 'foo' }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 28 }, identifierChain:[{ name: 'bar'}], tables: [{ identifierChain: [{ name: 'foo' }] }]}
+          { type: 'whereClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 19, last_column: 42 } },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 28 }, identifierChain:[{ name: 'bar'}], tables: [{ identifierChain: [{ name: 'foo' }] }]},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 42, last_column: 42 }}
         ]
       });
     });
@@ -149,9 +169,11 @@
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 48 } },
           { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'foo' }] }] },
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 18 }, identifierChain: [{ name: 'foo' }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 28 }, identifierChain:[{ name: 'bar'}], tables: [{ identifierChain: [{ name: 'foo' }] }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 33, last_column: 35 }, identifierChain: [{ name: 'id'}], tables: [{ identifierChain: [{ name: 'foo' }] }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 41, last_column: 43 }, identifierChain: [{ name: 'id'}], tables: [{ identifierChain: [{ name: 'foo' }] }]}
+          { type: 'whereClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 19, last_column: 48 }},
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 28 }, identifierChain: [{ name: 'bar' }], tables: [{ identifierChain: [{ name: 'foo' }] }] },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 33, last_column: 35 }, identifierChain: [{ name: 'id' }], tables: [{ identifierChain: [{ name: 'foo' }] }] },
+          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 41, last_column: 43 }, identifierChain: [{ name: 'id' }], tables: [{ identifierChain: [{ name: 'foo' }] }] },
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 48, last_column: 48 }}
         ]
       });
     });
@@ -193,6 +215,7 @@
           { type: 'column', location: { first_line: 5, last_line: 5, first_column: 10, last_column: 14 }, identifierChain: [{ name: 'code' }], tables: [{ identifierChain: [{ name: 'sample_07' }], alias: 's07' }] },
           { type: 'table', location: { first_line: 5, last_line: 5, first_column: 17, last_column: 20 }, identifierChain: [{ name: 'sample_08' }] },
           { type: 'column', location: { first_line: 5, last_line: 5, first_column: 21, last_column: 25 }, identifierChain: [{ name: 'code' }], tables: [{ identifierChain: [{ name: 'sample_08' }], alias: 's08' }] },
+          { type: 'whereClause', missing: false, location: { first_line: 6, last_line: 7, first_column: 1, last_column: 26 }},
           { type: 'table', location: { first_line: 7, last_line: 7, first_column: 3, last_column: 6 }, identifierChain: [{ name: 'sample_07' }] },
           { type: 'column', location: { first_line: 7, last_line: 7, first_column: 7, last_column: 13 }, identifierChain: [{ name: 'salary' }], tables: [{ identifierChain: [{ name: 'sample_07' }], alias: 's07' }] },
           { type: 'table', location: { first_line: 7, last_line: 7, first_column: 16, last_column: 19 }, identifierChain: [{ name: 'sample_08' }] },
@@ -200,21 +223,8 @@
           { type: 'table', location: { first_line: 8, last_line: 8, first_column: 10, last_column: 13 }, identifierChain: [{ name: 'sample_08' }] },
           { type: 'column', location: { first_line: 8, last_line: 8, first_column: 14, last_column: 20 }, identifierChain: [{ name: 'salary' }], tables: [{ identifierChain: [{ name: 'sample_08' }], alias: 's08' }] },
           { type: 'table', location: { first_line: 8, last_line: 8, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'sample_07' }] },
-          { type: 'column', location: { first_line: 8, last_line: 8, first_column: 25, last_column: 31 }, identifierChain: [{ name: 'salary'}], tables: [{ identifierChain: [{ name: 'sample_07' }], alias: 's07' }]}
-        ]
-      });
-    });
-
-    it('should report locations for "SELECT * FROM foo WHERE bar IN (id+1-1, id+1-2);|"', function() {
-      assertLocations({
-        beforeCursor: 'SELECT * FROM foo WHERE bar IN (id+1-1, id+1-2);',
-        expectedLocations: [
-          { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 48 } },
-          { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'foo' }] }] },
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 18 }, identifierChain: [{ name: 'foo' }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 28 }, identifierChain:[{ name: 'bar'}], tables: [{ identifierChain: [{ name: 'foo' }] }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 33, last_column: 35 }, identifierChain: [{ name: 'id'}], tables: [{ identifierChain: [{ name: 'foo' }] }]},
-          { type: 'column', location: { first_line: 1, last_line: 1, first_column: 41, last_column: 43 }, identifierChain: [{ name: 'id'}], tables: [{ identifierChain: [{ name: 'foo' }] }]}
+          { type: 'column', location: { first_line: 8, last_line: 8, first_column: 25, last_column: 31 }, identifierChain: [{ name: 'salary'}], tables: [{ identifierChain: [{ name: 'sample_07' }], alias: 's07' }]},
+          { type: 'limitClause', missing: false, location: { first_line: 9, last_line: 9, first_column: 1, last_column: 11 }}
         ]
       });
     });
@@ -228,8 +238,11 @@
           { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'bl' }], tables: [{ identifierChain: [{ name: 'blablabla' }] }, { subQuery: 's1' }] },
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 16, last_column: 25 }, identifierChain: [{ name: 'blablabla' }] },
           { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 39, last_column: 40 }, tables: [{ identifierChain: [{ name: 'blablabla' }] }] },
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 46, last_column: 55 }, identifierChain: [{ name: 'blablabla' }] }]
-
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 46, last_column: 55 }, identifierChain: [{ name: 'blablabla' }] },
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 55, last_column: 55 }}, // Subquery
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 55, last_column: 55 }}, // Subquery
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 59, last_column: 59 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 59, last_column: 59 }}]
       });
     });
 
@@ -261,10 +274,14 @@
           { type: 'database', location: { first_line: 6, last_line: 6, first_column: 8, last_column: 11 }, identifierChain: [{ name: 'db1' }]},
           { type: 'table', location: { first_line: 6, last_line: 6, first_column: 12, last_column: 15 }, identifierChain: [{ name: 'db1' }, { name: 'foo' }]},
           { type: 'table', location: { first_line: 6, last_line: 6, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'bar' }]},
+          { type: 'whereClause', missing: false, location: { first_line: 6, last_line: 6, first_column: 29, last_column: 67 } },
           { type: 'table', location: { first_line: 6, last_line: 6, first_column: 35, last_column: 38 }, identifierChain: [{ name: 'bar' }]},
           { type: 'column', location: { first_line: 6, last_line: 6, first_column: 39, last_column: 42 }, identifierChain: [{ name: 'bla' }], tables: [{ identifierChain: [{ name: 'bar' }], alias: 'baa' }] },
           { type: 'column', location: { first_line: 6, last_line: 6, first_column: 54, last_column: 57 }, identifierChain: [{ name: 'ble' }], tables: [{ identifierChain: [{ name: 'bla' }] }] },
-          { type: 'table', location: { first_line: 6, last_line: 6, first_column: 63, last_column: 66 }, identifierChain: [{ name: 'bla' }]}
+          { type: 'table', location: { first_line: 6, last_line: 6, first_column: 63, last_column: 66 }, identifierChain: [{ name: 'bla' }]},
+          { type: 'whereClause', missing: true, location: { first_line: 6, last_line: 6, first_column: 66, last_column: 66 } }, // Subquery
+          { type: 'limitClause', missing: true, location: { first_line: 6, last_line: 6, first_column: 66, last_column: 66 } }, // Subquery
+          { type: 'limitClause', missing: true, location: { first_line: 6, last_line: 6, first_column: 67, last_column: 67 } }
         ]
       });
     });
@@ -277,7 +294,9 @@
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11}, identifierChain: [{ name: 'testTableA' }]},
           { type: 'asterisk', location:{ first_line: 1, last_line: 1, first_column: 12, last_column: 13 }, tables: [{ alias: 'tta', identifierChain: [{ name: 'testTableA' }] }] },
           { type: 'table', location: { first_line: 1, last_line: 1, first_column: 19, last_column: 29}, identifierChain: [{ name: 'testTableA' }]},
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 35, last_column: 45}, identifierChain: [{ name: 'testTableB' }]}
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 35, last_column: 45}, identifierChain: [{ name: 'testTableB' }]},
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 45, last_column: 45 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 45, last_column: 45 }}
         ]
       });
     });
@@ -288,7 +307,9 @@
         expectedLocations: [
           { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 31 } },
           { type: 'function', location:{ first_line: 1, last_line: 1, first_column: 8, last_column: 12}, function: 'count'},
-          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 22, last_column: 31}, identifierChain: [{ name: 'testTable' }]}
+          { type: 'table', location: { first_line: 1, last_line: 1, first_column: 22, last_column: 31}, identifierChain: [{ name: 'testTable' }]},
+          { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 31, last_column: 31 }},
+          { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 31, last_column: 31 }}
         ]
       });
     });
@@ -327,6 +348,7 @@
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 68 } },
             { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, tables: [{ alias: 't1', identifierChain: [{ name: 'testTable' }] }] },
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 24 }, identifierChain: [{ name: 'testTable' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 27, last_column: 27 }},
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 37, last_column: 39 }, identifierChain: [{ name: 'testTable' }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 40, last_column: 41 }, identifierChain: [{ name: 'a' }], tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't1' }]},
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 47, last_column: 49 }, identifierChain: [{ name: 'testTable' }]},
@@ -335,14 +357,19 @@
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 56, last_column: 57 }, identifierChain: [{ name: 'c' }], tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't1' }]},
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 64, last_column: 66 }, identifierChain: [{ name: 'testTable' }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 67, last_column: 68 }, identifierChain: [{ name: 'd' }], tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't1' }]},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 68, last_column: 68 }},
             { type: 'statement', location: { first_line: 1, last_line: 2, first_column: 69, last_column: 33 } },
             { type: 'table', location: { first_line: 2, last_line: 2, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'testTable2' }]},
             { type: 'column', location: { first_line: 2, last_line: 2, first_column: 11, last_column: 14 }, identifierChain: [{ name: 'bla' }], tables: [{ identifierChain: [{ name: 'testTable2' }], alias: 't1' }]},
             { type: 'table', location: { first_line: 2, last_line: 2, first_column: 20, last_column: 30 }, identifierChain: [{ name: 'testTable2' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 33, last_column: 33 }},
+            { type: 'limitClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 33, last_column: 33 }},
             { type: 'statement', location: { first_line: 2, last_line: 3, first_column: 34, last_column: 43 } },
             { type: 'asterisk', location: { first_line: 3, last_line: 3, first_column: 8, last_column: 9 }, tables: [{ alias: 't3', identifierChain: [{ name: 'testTable3' }]}, { alias: 't4', identifierChain: [{ name: 'testTable4' }] }] },
             { type: 'table', location: { first_line: 3, last_line: 3, first_column: 15, last_column: 25 }, identifierChain: [{ name: 'testTable3' }]},
-            { type: 'table', location: { first_line: 3, last_line: 3, first_column: 30, last_column: 40 }, identifierChain: [{ name: 'testTable4' }]}
+            { type: 'table', location: { first_line: 3, last_line: 3, first_column: 30, last_column: 40 }, identifierChain: [{ name: 'testTable4' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 3, last_line: 3, first_column: 43, last_column: 43 }},
+            { type: 'limitClause', missing: true, location: { first_line: 3, last_line: 3, first_column: 43, last_column: 43 }}
           ]
         });
       });
@@ -362,7 +389,9 @@
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 90, last_column: 92 }, identifierChain: [{ name: 'table1' }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 93, last_column: 95 }, identifierChain: [{ name: 'c1' }], tables: [{ identifierChain: [{ name: 'table1' }], alias: 't1' }]},
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 98, last_column: 104 }, identifierChain: [{ name: 'table2' }]},
-            { type: 'column', location: { first_line: 1, last_line: 1, first_column: 105, last_column: 107 }, identifierChain: [{ name: 'c2' }], tables: [{ identifierChain: [{ name: 'table2' }] }]}
+            { type: 'column', location: { first_line: 1, last_line: 1, first_column: 105, last_column: 107 }, identifierChain: [{ name: 'c2' }], tables: [{ identifierChain: [{ name: 'table2' }] }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 108, last_column: 108 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 108, last_column: 108 }}
           ]
         });
       });
@@ -375,9 +404,13 @@
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 51 } },
             { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'foo' }] }] },
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 18 }, identifierChain: [{ name: 'foo' }]},
+            { type: 'whereClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 19, last_column: 51 }},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 28 }, identifierChain:[{ name: 'bar'}], tables: [{ identifierChain: [{ name: 'foo' }] }]},
             { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 40, last_column: 41 }, tables: [{ identifierChain: [{ name: 'bla' }] }] },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 47, last_column: 50 }, identifierChain: [{ name: 'bla' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 47, last_column: 50 }, identifierChain: [{ name: 'bla' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 50, last_column: 50 }}, // Subquery
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 50, last_column: 50 }}, // Subquery
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 51, last_column: 51 }}
           ]
         });
       });
@@ -389,7 +422,9 @@
           afterCursor: '    FROM    testTableA',
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 32 } },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 22, last_column: 32}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 22, last_column: 32}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 32, last_column: 32 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 32, last_column: 32 }}
           ]
         });
       });
@@ -402,7 +437,9 @@
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 34 } },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 10, last_column: 11 }, identifierChain: [{ name: 'a' }], tables: [{ identifierChain: [{ name: 'testTableA' }] }]},
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 34}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 34}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 34, last_column: 34 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 34, last_column: 34 }}
           ]
         });
       });
@@ -414,7 +451,9 @@
           afterCursor: ' FROM testTableA',
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 27 } },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 17, last_column: 27}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 17, last_column: 27}, identifierChain: [{ name: 'testTableA' }]},
+            { 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 }}
           ]
         });
       });
@@ -426,7 +465,9 @@
           afterCursor: ' \nFROM testTableA',
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 2, first_column: 1, last_column: 16 } },
-            { type: 'table', location: { first_line: 2, last_line: 2, first_column: 6, last_column: 16}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 2, last_line: 2, first_column: 6, last_column: 16}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 16, last_column: 16 }},
+            { type: 'limitClause', missing: true, location: { first_line: 2, last_line: 2, first_column: 16, last_column: 16 }}
           ]
         });
       });
@@ -438,7 +479,9 @@
           afterCursor: 'bbbb FROM testTableA',
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 28 } },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 18, last_column: 28}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 18, last_column: 28}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 28, last_column: 28 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 28, last_column: 28 }}
           ]
         });
       });
@@ -450,7 +493,9 @@
           afterCursor: 'bbbb FROM testTableA',
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 33 } },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 23, last_column: 33}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 23, last_column: 33}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 33, last_column: 33 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 33, last_column: 33 }}
           ]
         });
       });
@@ -463,7 +508,9 @@
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 37 } },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11}, identifierChain: [{ name: 'foo' }], tables: [{ identifierChain: [{ name: 'testTableA' }] }]},
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 27, last_column: 37}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 27, last_column: 37}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 37, last_column: 37 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 37, last_column: 37 }}
           ]
         });
       });
@@ -477,7 +524,9 @@
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 40 } },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9}, identifierChain: [{ name: 'b' }], tables: [{ identifierChain: [{ name: 'testTableA' }] }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 11, last_column: 14}, identifierChain: [{ name: 'foo' }], tables: [{ identifierChain: [{ name: 'testTableA' }] }]},
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 30, last_column: 40}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 30, last_column: 40}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 40, last_column: 40 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 40, last_column: 40 }}
           ]
         });
       });
@@ -490,7 +539,9 @@
           expectedLocations: [
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 38 } },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11}, identifierChain: [{ name: 'foo' }], tables: [{ identifierChain: [{ name: 'testTableA' }] }]},
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 28, last_column: 38}, identifierChain: [{ name: 'testTableA' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 28, last_column: 38}, identifierChain: [{ name: 'testTableA' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 38, last_column: 38 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 38, last_column: 38 }}
           ]
         });
       });
@@ -504,7 +555,9 @@
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 33 } },
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11 }, identifierChain: [{ name: 'some_tbl' }] },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 12, last_column: 15 }, identifierChain: [{ name: 'col' }], tables: [{ identifierChain: [{ name: 'some_tbl' }], alias: 'tbl' }] },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 29 }, identifierChain: [{ name: 'some_tbl' }] }
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 29 }, identifierChain: [{ name: 'some_tbl' }] },
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 33, last_column: 33 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 33, last_column: 33 }}
           ]
         });
       });
@@ -519,7 +572,9 @@
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 11 }, identifierChain: [{ name: 'some_tbl' }] },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 12, last_column: 15 }, identifierChain: [{ name: 'col' }], tables: [{ identifierChain: [{ name: 'some_tbl' }], alias: 'tbl' }] },
             { type: 'complex', location: { first_line: 1, last_line: 1, first_column: 16, last_column: 20 }, identifierChain: [{ name: 'col' }, { name: 'cplx' }], tables: [{ identifierChain: [{ name: 'some_tbl' }], alias: 'tbl' }] },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 34 }, identifierChain: [{ name: 'some_tbl' }] }
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 34 }, identifierChain: [{ name: 'some_tbl' }] },
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 38, last_column: 38 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 38, last_column: 38 }}
           ]
         });
       });
@@ -534,7 +589,9 @@
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 16 }, identifierChain: [{ name: 'some_tbl' }] },
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 17, last_column: 20 }, identifierChain: [{ name: 'col' }], tables: [{ identifierChain: [{ name: 'some_tbl' }] }] },
             { type: 'complex', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 25 }, identifierChain: [{ name: 'col' }, { name: 'cplx' }], tables: [{ identifierChain: [{ name: 'some_tbl' }] }] },
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 39 }, identifierChain: [{ name: 'some_tbl' }] }
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 39 }, identifierChain: [{ name: 'some_tbl' }] },
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 39, last_column: 39 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 39, last_column: 39 }}
           ]
         });
       });
@@ -555,7 +612,9 @@
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 51, last_column: 54 }, identifierChain: [{ name: 'bla' }], tables: [{ identifierChain: [{ name: 'testTableA' }], alias: 'tta' }]},
             { type: 'function', location: { first_line: 1, last_line: 1, first_column: 56, last_column: 58 }, function: 'cos' },
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 68, last_column: 78 }, identifierChain: [{ name: 'testTableA' }]},
-            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 84, last_column: 94 }, identifierChain: [{ name: 'testTableB' }]}
+            { type: 'table', location: { first_line: 1, last_line: 1, first_column: 84, last_column: 94 }, identifierChain: [{ name: 'testTableB' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 94, last_column: 94 }},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 94, last_column: 94 }}
           ]
         });
       });
@@ -594,10 +653,14 @@
             { type: 'function', location: { first_line: 1, last_line: 1, first_column: 178, last_column: 181 }, function: 'year' },
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 183, last_column: 187 }, identifierChain: [{ name:'tran' }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 188, last_column: 194 }, identifierChain: [{ name: 'tran_d' }], tables: [{ identifierChain: [{ name:'tran' }] }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 218, last_column: 218 }},
             { type: 'database', location: { first_line: 1, last_line: 1, first_column: 228, last_column: 234 }, identifierChain: [{ name: 'tstDb1' }]},
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 235, last_column: 237 }, identifierChain: [{ name:'tstDb1' },{ name: 'b1' }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 238, last_column: 241 }, identifierChain: [{ name: 'cat' }], tables: [{ identifierChain: [{ name:'tstDb1' }, {name: 'b1' }] }]},
-            { type: 'column', location: { first_line: 1, last_line: 1, first_column: 256, last_column: 257 }, identifierChain: [{ name: 'r' }], tables: [{ subQuery: 'tmp' }]}
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 241, last_column: 241 }},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 246, last_column: 246 }},
+            { type: 'column', location: { first_line: 1, last_line: 1, first_column: 256, last_column: 257 }, identifierChain: [{ name: 'r' }], tables: [{ subQuery: 'tmp' }]},
+            { type: 'limitClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 263, last_column: 271 }}
           ]
         });
       });
@@ -611,10 +674,12 @@
             { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 53 } },
             { type: 'asterisk', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 9 }, tables: [{ identifierChain: [{ name: 'testTable' }] }] },
             { type: 'table', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 24 }, identifierChain: [{ name: 'testTable' }]},
+            { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 24, last_column: 24 }},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 34, last_column: 35 }, identifierChain: [{ name: 'a'}], tables: [{ identifierChain: [{ name:'testTable' }] }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 41, last_column: 42 }, identifierChain: [{ name: 'b'}], tables: [{ identifierChain: [{ name:'testTable' }] }]},
             { type: 'column', location: { first_line: 1, last_line: 1, first_column: 44, last_column: 45 }, identifierChain: [{ name: 'c'}], tables: [{ identifierChain: [{ name:'testTable' }] }]},
-            { type: 'column', location: { first_line: 1, last_line: 1, first_column: 52, last_column: 53 }, identifierChain: [{ name: 'd'}], tables: [{ identifierChain: [{ name:'testTable' }] }]}
+            { type: 'column', location: { first_line: 1, last_line: 1, first_column: 52, last_column: 53 }, identifierChain: [{ name: 'd'}], tables: [{ identifierChain: [{ name:'testTable' }] }]},
+            { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 53, last_column: 53 }}
           ]
         });
       });

+ 53 - 17
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpecSelect.js

@@ -343,7 +343,9 @@
               { type: 'function', location: { first_line: 1, last_line: 1, first_column: 29, last_column: 32 }, function: 'avg' },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 34, last_column: 36 }, identifierChain: [{ name: 'id' }], tables: [{ identifierChain: [{ name: 'autocomp_test' }], alias: 'tst' }] },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 39, last_column: 42 }, identifierChain: [{ name: 'avg' }], tables: [{ identifierChain: [{ name: 'autocomp_test' }], alias: 'tst' }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 48, last_column: 61 }, identifierChain: [{ name: 'autocomp_test' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 48, last_column: 61 }, identifierChain: [{ name: 'autocomp_test' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 65, last_column: 65 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 65, last_column: 65 } }
             ],
             lowerCase: true
           }
@@ -549,7 +551,9 @@
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 18, last_column: 19 }, identifierChain:[{ name: 'a'}], tables: [{ identifierChain: [{ name: 'tbl' }] }] },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 22 }, identifierChain:[{ name: 'b'}], tables: [{ identifierChain: [{ name: 'tbl' }] }] },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 24, last_column: 25 }, identifierChain:[{ name: 'c'}], tables: [{ identifierChain: [{ name: 'tbl' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 34 }, identifierChain: [{ name: 'tbl' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 34 }, identifierChain: [{ name: 'tbl' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 34, last_column: 34 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 34, last_column: 34 } }
             ]
           }
         });
@@ -805,7 +809,9 @@
             locations: [
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 41 } },
               { type: 'database', location: { first_line: 1, last_line: 1, first_column: 14, last_column: 28}, identifierChain: [{ name: 'database one' }]},
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 29, last_column: 41}, identifierChain: [{ name: 'database one' }, { name: 'test table' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 29, last_column: 41}, identifierChain: [{ name: 'database one' }, { name: 'test table' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 41, last_column: 41 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 41, last_column: 41 } }
             ]
           }
         });
@@ -963,9 +969,11 @@
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 15, last_column: 16 }, identifierChain: [{ name: 'c' }], tables: [{ identifierChain: [{ name: 'testTable' }] }]},
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 18, last_column: 19 }, identifierChain: [{ name: 'd' }], tables: [{ identifierChain: [{ name: 'testTable' }] }]},
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 25, last_column: 34 }, identifierChain: [{ name: 'testTable' }] },
+              { type: 'whereClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 35, last_column: 62 } },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 41, last_column: 42 }, identifierChain: [{ name: 'a' }], tables: [{ identifierChain: [{ name: 'testTable' }] }]},
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 54, last_column: 55 }, identifierChain: [{ name: 'b' }], tables: [{ identifierChain: [{ name: 'testTable' }] }]},
-              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 72, last_column: 73 }, identifierChain: [{ name: 'c' }], tables: [{ identifierChain: [{ name: 'testTable' }] }]}
+              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 72, last_column: 73 }, identifierChain: [{ name: 'c' }], tables: [{ identifierChain: [{ name: 'testTable' }] }]},
+              { type: 'limitClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 79, last_column: 87 } }
             ]
           }
         });
@@ -1546,7 +1554,9 @@
             locations: [
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 23 } },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'bl' }], tables: [{ identifierChain: [{ name: 'bar' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 20, last_column: 23 }, identifierChain: [{ name: 'bar' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 20, last_column: 23 }, identifierChain: [{ name: 'bar' }] },
+              { 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 } }
             ],
             lowerCase: false,
             suggestValues: { partialQuote: '\'', missingEndQuote: true },
@@ -1564,7 +1574,9 @@
             locations: [
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 24 } },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'bl' }], tables: [{ identifierChain: [{ name: 'bar' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'bar' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'bar' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 24, last_column: 24 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 24, last_column: 24 } }
             ],
             lowerCase: false,
             suggestValues: { partialQuote: '\'', missingEndQuote: false },
@@ -1582,7 +1594,9 @@
             locations: [
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 29 } },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'bl' }], tables: [{ identifierChain: [{ name: 'bar' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 29 }, identifierChain: [{ name: 'bar' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 29 }, identifierChain: [{ name: 'bar' }] },
+              { 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 } }
             ],
             lowerCase: false,
             suggestValues: { partialQuote: '\'', missingEndQuote: false },
@@ -1613,7 +1627,9 @@
             locations: [
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 24 } },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'bl' }], tables: [{ identifierChain: [{ name: 'bar' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'bar' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'bar' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 24, last_column: 24 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 24, last_column: 24 } }
             ],
             lowerCase: false,
             suggestValues: { partialQuote: '"', missingEndQuote: false },
@@ -1631,7 +1647,9 @@
             locations: [
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 29 } },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'bl' }], tables: [{ identifierChain: [{ name: 'bar' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 29 }, identifierChain: [{ name: 'bar' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 26, last_column: 29 }, identifierChain: [{ name: 'bar' }] },
+              { 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 } }
             ],
             lowerCase: false,
             suggestValues: { partialQuote: '"', missingEndQuote: false },
@@ -1811,7 +1829,9 @@
               { type: 'database', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10 }, identifierChain: [{ name: 'db' }] },
               { type: 'function', location: { first_line: 1, last_line: 1, first_column: 11, last_column: 19 }, identifierChain: [{ name: 'db' }, { name: 'customUdf' }], function: 'customudf' },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 21, last_column: 24 }, identifierChain: [{ name: 'col' }], tables: [{ identifierChain: [{ name: 'bar' }] }] },
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 34 }, identifierChain: [{ name: 'bar' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 31, last_column: 34 }, identifierChain: [{ name: 'bar' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 34, last_column: 34 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 34, last_column: 34 } }
             ]
           }
         });
@@ -2875,7 +2895,9 @@
                 { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 81 } },
                 { type: 'table', location: { first_line: 1, last_line: 1, first_column: 14, last_column: 23 }, identifierChain: [{ name: 'testTable' }] },
                 { type: 'function', location: { first_line: 1, last_line: 1, first_column: 37, last_column: 43 }, function: 'explode' },
-                { type: 'column', location: { first_line: 1, last_line: 1, first_column: 45, last_column: 54 }, identifierChain: [{ name: 'testArray' }], tables: [{ identifierChain: [{ name: 'testTable' }] }] }
+                { type: 'column', location: { first_line: 1, last_line: 1, first_column: 45, last_column: 54 }, identifierChain: [{ name: 'testArray' }], tables: [{ identifierChain: [{ name: 'testTable' }] }] },
+                { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 81, last_column: 81 } },
+                { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 81, last_column: 81 } }
               ],
               suggestAggregateFunctions: { tables: [{ identifierChain: [{ name: 'testTable' }] }] },
               suggestAnalyticFunctions: true,
@@ -3041,7 +3063,9 @@
                 { type: 'column', location: { first_line: 6, last_line: 6, first_column: 28, last_column: 38 }, identifierChain: [{ name: 'testArrayA'}], tables: [{ identifierChain: [{ name: 'testTable2' }], alias: 'tt2' }] },
                 { type: 'function', location: { first_line: 7, last_line: 7, first_column: 16, last_column: 22 }, function: 'explode'},
                 { type: 'table', location: { first_line: 7, last_line: 7, first_column: 24, last_column: 27 }, identifierChain: [{ name: 'testTable2' }]},
-                { type: 'column', location: { first_line: 7, last_line: 7, first_column: 28, last_column: 38 }, identifierChain: [{ name: 'testArrayB'}], tables: [{ identifierChain: [{ name: 'testTable2' }], alias: 'tt2' }] }
+                { type: 'column', location: { first_line: 7, last_line: 7, first_column: 28, last_column: 38 }, identifierChain: [{ name: 'testArrayB'}], tables: [{ identifierChain: [{ name: 'testTable2' }], alias: 'tt2' }] },
+                { type: 'whereClause', missing: true, location: { first_line: 7, last_line: 7, first_column: 67, last_column: 67 } },
+                { type: 'limitClause', missing: true, location: { first_line: 7, last_line: 7, first_column: 67, last_column: 67 } }
               ],
               suggestColumns: { source: 'select', identifierChain: [{ name: 'testArrayB' }, { name: 'item' }], tables: [{ identifierChain: [{ name: 'testTable2' }] }] },
               lowerCase: false
@@ -3252,11 +3276,13 @@
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 8, last_column: 10}, identifierChain: [{ name: 'testMap' }], tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't' }]},
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 17, last_column :26}, identifierChain: [{ name: 'testTable' }]},
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 30, last_column: 31}, identifierChain: [{ name: 'testTable' }]},
-              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 32, last_column :39}, identifierChain: [{ name: 'testMap'}], tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't'  }]}
+              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 32, last_column :39}, identifierChain: [{ name: 'testMap'}], tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't'  }]},
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 42, last_column: 42 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 42, last_column: 42 } }
             ],
             suggestKeywords: ['*'],
             lowerCase: false,
-            suggestColumns: { source: 'select', identifierChain: [{ name: 'testMap' }], tables: [{ identifierChain: [{ name: 'testTable' }] }] },
+            suggestColumns: { source: 'select', identifierChain: [{ name: 'testMap' }], tables: [{ identifierChain: [{ name: 'testTable' }] }] }
           }
         });
       });
@@ -6160,7 +6186,9 @@
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 62, last_column: 72 }, identifierChain: [{ name: 'testTable1' }]},
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 73, last_column: 84}, identifierChain: [{ name: 'testColumn1'}], tables: [{ identifierChain: [{ name: 'testTable1' }] }] },
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 87, last_column: 97 }, identifierChain: [{ name: 'testTable2' }]},
-              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 98, last_column: 109}, identifierChain: [{ name: 'testColumn3'}], tables: [{ identifierChain: [{ name: 'testTable2' }] }] }
+              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 98, last_column: 109}, identifierChain: [{ name: 'testColumn3'}], tables: [{ identifierChain: [{ name: 'testTable2' }] }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 109, last_column: 109 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 109, last_column: 109 } }
             ],
             suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable1' }] }, { identifierChain: [{ name: 'testTable2' }] }] },
             suggestIdentifiers: [{ name: 'testTable1.', type: 'table' }, { name: 'testTable2.', type: 'table' }],
@@ -6906,9 +6934,13 @@
               { type: 'statement', location: { first_line: 1, last_line: 1, first_column: 1, last_column: 103 } },
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 39, last_column: 41}, identifierChain: [{ name: 't1' }] },
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 43, last_column: 45}, identifierChain: [{ name: 't2' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 52, last_column: 52 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 52, last_column: 52 } },
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 74, last_column: 76}, identifierChain: [{ name: 't3' }]},
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 77, last_column: 80}, identifierChain: [{ name: 'foo'}], tables: [{ identifierChain: [{ name: 't3' }] }]},
-              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 86, last_column: 88}, identifierChain: [{ name: 't3' }] }
+              { type: 'table', location: { first_line: 1, last_line: 1, first_column: 86, last_column: 88}, identifierChain: [{ name: 't3' }] },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 88, last_column: 88 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 88, last_column: 88 } }
             ]
           }
         });
@@ -6925,7 +6957,11 @@
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 14, last_column: 23}, identifierChain: [{ name: 'testTable' }] },
               { type: 'column', location: { first_line: 1, last_line: 1, first_column: 36, last_column: 39}, identifierChain: [{ name: 'bla'}], tables: [{ identifierChain: [{ name: 'abc' }] }] },
               { type: 'table', location: { first_line: 1, last_line: 1, first_column: 45, last_column: 48}, identifierChain: [{ name: 'abc' }] },
-              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 55, last_column: 58}, identifierChain: [{ name: 'foo'}], tables: [{ identifierChain: [{ name: 'abc' }] }] }
+              { type: 'whereClause', missing: false, location: { first_line: 1, last_line: 1, first_column: 49, last_column: 62 } },
+              { type: 'column', location: { first_line: 1, last_line: 1, first_column: 55, last_column: 58}, identifierChain: [{ name: 'foo'}], tables: [{ identifierChain: [{ name: 'abc' }] }] },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 62, last_column: 62 } },
+              { type: 'whereClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 67, last_column: 67 } },
+              { type: 'limitClause', missing: true, location: { first_line: 1, last_line: 1, first_column: 67, last_column: 67 } }
             ],
             suggestAggregateFunctions: { tables: [{ identifierChain: [{ name: 'testTable' }], alias: 'tt' }] },
             suggestAnalyticFunctions: true,

+ 38 - 1
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlAutocompleteParser.js

@@ -683,11 +683,20 @@ case 860: case 1319: case 1851: case 2242: case 2259:
 
      parser.suggestKeywords(['SELECT']);
    
+break;
+case 866: case 867:
+
+     parser.addClauseLocation('whereClause', _$[$0-1], $$[$0].whereClauseLocation);
+     parser.addClauseLocation('limitClause', $$[$0].limitClausePreceding || _$[$0-1], $$[$0].limitClauseLocation);
+   
 break;
 case 868:
 
      var keywords = [];
 
+     parser.addClauseLocation('whereClause', _$[$0-3], $$[$0-1].whereClauseLocation);
+     parser.addClauseLocation('limitClause', $$[$0-2].limitClausePreceding || _$[$0-3], $$[$0-2].limitClauseLocation);
+
      if ($$[$0-3]) {
        if (!$$[$0-3].hasLateralViews && typeof $$[$0-3].tableReferenceList.hasJoinCondition !== 'undefined' && !$$[$0-3].tableReferenceList.hasJoinCondition) {
          keywords.push({ value: 'ON', weight: 3 });
@@ -777,8 +786,12 @@ case 869:
      //   or 'AND' based on type
 
      if (!$$[$0-1]) {
+       parser.addClauseLocation('whereClause', _$[$0-2]);
+       parser.addClauseLocation('limitClause', _$[$0-2]);
        return;
      }
+     parser.addClauseLocation('whereClause', _$[$0-2], $$[$0-1].whereClauseLocation);
+     parser.addClauseLocation('limitClause', $$[$0-1].limitClausePreceding || _$[$0-2], $$[$0-1].limitClauseLocation);
      var keywords = [];
 
      if ($$[$0-1].suggestColRefKeywords) {
@@ -838,6 +851,10 @@ case 877:
        this.$ = {};
      }
 
+     this.$.whereClauseLocation = $$[$0-7] ? _$[$0-7] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-6], _$[$0-6], $$[$0-7], _$[$0-7]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
+
      if (!$$[$0-7] && !$$[$0-6] && !$$[$0-5] && !$$[$0-4] && !$$[$0-3] && !$$[$0-2] && !$$[$0-1] && !$$[$0]) {
        this.$.suggestFilters = { prefix: 'WHERE', tablePrimaries: parser.yy.latestTablePrimaries.concat() };
      }
@@ -890,6 +907,9 @@ case 886:
      if (!$$[$0-6] && !$$[$0-5] && !$$[$0-4] && !$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-6], _$[$0-6], $$[$0-8], _$[$0-8]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 887:
@@ -909,6 +929,9 @@ case 887:
      if (!$$[$0-5] && !$$[$0-4] && !$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-7], _$[$0-7]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 888:
@@ -921,6 +944,9 @@ case 888:
      if (!$$[$0-4] && !$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-6], _$[$0-6]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 889:
@@ -930,7 +956,9 @@ case 889:
      if (!$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
-
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-5], _$[$0-5]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 890:
@@ -940,6 +968,9 @@ case 890:
        keywords = keywords.concat(parser.createWeightedKeywords($$[$0-4].suggestKeywords, 5));
      }
      this.$ = { suggestKeywords: keywords, cursorAtEnd: !$$[$0-2] && !$$[$0-1] && !$$[$0] };
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-4], _$[$0-4]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 891:
@@ -949,12 +980,18 @@ case 891:
        keywords = keywords.concat(parser.createWeightedKeywords($$[$0-3].suggestKeywords, 4));
      }
      this.$ = { suggestKeywords: keywords, cursorAtEnd: !$$[$0-1] && !$$[$0] };
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = _$[$0-3];
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 892:
 
      var keywords = parser.getKeywordsForOptionalsLR([$$[$0]], [{ value: 'OFFSET', weight: 2 }], [parser.isImpala()]);
      this.$ = { suggestKeywords: keywords, cursorAtEnd: !$$[$0] };
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-6], _$[$0-6], $$[$0-7], _$[$0-7], $$[$0-8], _$[$0-8]);
+     this.$.limitClauseLocation = $$[$0-2] ? _$[$0-2] : undefined;
    
 break;
 case 893:

+ 19 - 3
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlParseSupport.js

@@ -1271,6 +1271,22 @@ var SqlParseSupport = (function () {
       });
     };
 
+    parser.firstDefined = function () {
+      for (var i = 0; i + 1 < arguments.length; i += 2) {
+        if (arguments[i]) {
+          return arguments[i + 1];
+        }
+      }
+    };
+
+    parser.addClauseLocation = function (type, precedingLocation, locationIfPresent) {
+      parser.yy.locations.push({
+        type: type,
+        missing: !locationIfPresent,
+        location: adjustLocationForCursor(locationIfPresent || { first_line: precedingLocation.last_line, first_column: precedingLocation.last_column, last_line: precedingLocation.last_line, last_column: precedingLocation.last_column })
+      })
+    };
+
     parser.addHdfsLocation = function (location, path) {
       parser.yy.locations.push({
         type: 'hdfs',
@@ -1550,9 +1566,9 @@ var SqlParseSupport = (function () {
     'identifyPartials', 'expandLateralViews', 'expandIdentifierChain', 'getSubQuery', 'addTablePrimary', 'suggestFileFormats', 'getKeywordsForOptionalsLR',
     'suggestDdlAndDmlKeywords', 'checkForSelectListKeywords', 'checkForKeywords', 'createWeightedKeywords', 'suggestKeywords', 'suggestColRefKeywords',
     'suggestTablesOrColumns', 'suggestFunctions', 'suggestAggregateFunctions', 'suggestAnalyticFunctions', 'suggestColumns', 'suggestGroupBys',
-    'suggestOrderBys', 'suggestFilters', 'suggestKeyValues', 'suggestTables', 'addFunctionLocation', 'addStatementLocation', 'addHdfsLocation',
-    'addDatabaseLocation', 'addTableLocation', 'addAsteriskLocation', 'addColumnLocation', 'addUnknownLocation', 'suggestDatabases', 'suggestHdfs',
-    'suggestValues', 'handleQuotedValueWithCursor'];
+    'suggestOrderBys', 'suggestFilters', 'suggestKeyValues', 'suggestTables', 'addFunctionLocation', 'addStatementLocation', 'firstDefined',
+    'addClauseLocation', 'addHdfsLocation', 'addDatabaseLocation', 'addTableLocation', 'addAsteriskLocation', 'addColumnLocation', 'addUnknownLocation',
+    'suggestDatabases', 'suggestHdfs', 'suggestValues', 'handleQuotedValueWithCursor'];
 
   var SYNTAX_PARSER_NOOP = function () {};
 

+ 38 - 1
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlSyntaxParser.js

@@ -678,11 +678,20 @@ case 852: case 1277: case 1786: case 2182: case 2199:
 
      parser.suggestKeywords(['SELECT']);
    
+break;
+case 858: case 859:
+
+     parser.addClauseLocation('whereClause', _$[$0-1], $$[$0].whereClauseLocation);
+     parser.addClauseLocation('limitClause', $$[$0].limitClausePreceding || _$[$0-1], $$[$0].limitClauseLocation);
+   
 break;
 case 860:
 
      var keywords = [];
 
+     parser.addClauseLocation('whereClause', _$[$0-3], $$[$0-1].whereClauseLocation);
+     parser.addClauseLocation('limitClause', $$[$0-2].limitClausePreceding || _$[$0-3], $$[$0-2].limitClauseLocation);
+
      if ($$[$0-3]) {
        if (!$$[$0-3].hasLateralViews && typeof $$[$0-3].tableReferenceList.hasJoinCondition !== 'undefined' && !$$[$0-3].tableReferenceList.hasJoinCondition) {
          keywords.push({ value: 'ON', weight: 3 });
@@ -772,8 +781,12 @@ case 861:
      //   or 'AND' based on type
 
      if (!$$[$0-1]) {
+       parser.addClauseLocation('whereClause', _$[$0-2]);
+       parser.addClauseLocation('limitClause', _$[$0-2]);
        return;
      }
+     parser.addClauseLocation('whereClause', _$[$0-2], $$[$0-1].whereClauseLocation);
+     parser.addClauseLocation('limitClause', $$[$0-1].limitClausePreceding || _$[$0-2], $$[$0-1].limitClauseLocation);
      var keywords = [];
 
      if ($$[$0-1].suggestColRefKeywords) {
@@ -833,6 +846,10 @@ case 869:
        this.$ = {};
      }
 
+     this.$.whereClauseLocation = $$[$0-7] ? _$[$0-7] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-6], _$[$0-6], $$[$0-7], _$[$0-7]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
+
      if (!$$[$0-7] && !$$[$0-6] && !$$[$0-5] && !$$[$0-4] && !$$[$0-3] && !$$[$0-2] && !$$[$0-1] && !$$[$0]) {
        this.$.suggestFilters = { prefix: 'WHERE', tablePrimaries: parser.yy.latestTablePrimaries.concat() };
      }
@@ -885,6 +902,9 @@ case 878:
      if (!$$[$0-6] && !$$[$0-5] && !$$[$0-4] && !$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-6], _$[$0-6], $$[$0-8], _$[$0-8]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 879:
@@ -904,6 +924,9 @@ case 879:
      if (!$$[$0-5] && !$$[$0-4] && !$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-7], _$[$0-7]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 880:
@@ -916,6 +939,9 @@ case 880:
      if (!$$[$0-4] && !$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-6], _$[$0-6]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 881:
@@ -925,7 +951,9 @@ case 881:
      if (!$$[$0-3]) {
        parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
      }
-
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-3], _$[$0-3], $$[$0-5], _$[$0-5]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 882:
@@ -935,6 +963,9 @@ case 882:
        keywords = keywords.concat(parser.createWeightedKeywords($$[$0-4].suggestKeywords, 5));
      }
      this.$ = { suggestKeywords: keywords, cursorAtEnd: !$$[$0-2] && !$$[$0-1] && !$$[$0] };
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-2], _$[$0-2], $$[$0-4], _$[$0-4]);
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 883:
@@ -944,12 +975,18 @@ case 883:
        keywords = keywords.concat(parser.createWeightedKeywords($$[$0-3].suggestKeywords, 4));
      }
      this.$ = { suggestKeywords: keywords, cursorAtEnd: !$$[$0-1] && !$$[$0] };
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = _$[$0-3];
+     this.$.limitClauseLocation = $$[$0-1] ? _$[$0-1] : undefined;
    
 break;
 case 884:
 
      var keywords = parser.getKeywordsForOptionalsLR([$$[$0]], [{ value: 'OFFSET', weight: 2 }], [parser.isImpala()]);
      this.$ = { suggestKeywords: keywords, cursorAtEnd: !$$[$0] };
+     this.$.whereClauseLocation = $$[$0-8] ? _$[$0-8] : undefined;
+     this.$.limitClausePreceding = parser.firstDefined($$[$0-3], _$[$0-3], $$[$0-4], _$[$0-4], $$[$0-5], _$[$0-5], $$[$0-6], _$[$0-6], $$[$0-7], _$[$0-7], $$[$0-8], _$[$0-8]);
+     this.$.limitClauseLocation = $$[$0-2] ? _$[$0-2] : undefined;
    
 break;
 case 888: