Преглед изворни кода

HUE-8958 [editor] Honor the closest preceding USE statement when executing and editing statements

Johan Ahlen пре 6 година
родитељ
комит
b6492890d6

+ 14 - 0
desktop/core/src/desktop/js/apps/notebook/snippet.js

@@ -518,6 +518,20 @@ class Snippet {
       'editor.active.statement.changed',
       statementDetails => {
         if (self.ace() && self.ace().container.id === statementDetails.id) {
+          for (let i = statementDetails.precedingStatements.length - 1; i >= 0; i--) {
+            if (statementDetails.precedingStatements[i].database) {
+              self.availableDatabases().some(availableDatabase => {
+                if (
+                  availableDatabase.toLowerCase() ===
+                  statementDetails.precedingStatements[i].database.toLowerCase()
+                ) {
+                  self.database(availableDatabase);
+                  return true;
+                }
+              });
+              break;
+            }
+          }
           if (statementDetails.activeStatement) {
             self.positionStatement(statementDetails.activeStatement);
           } else {

+ 14 - 0
desktop/core/src/desktop/js/apps/notebook2/snippet.js

@@ -358,6 +358,20 @@ class Snippet {
       'editor.active.statement.changed',
       statementDetails => {
         if (self.ace() && self.ace().container.id === statementDetails.id) {
+          for (let i = statementDetails.precedingStatements.length - 1; i >= 0; i--) {
+            if (statementDetails.precedingStatements[i].database) {
+              self.availableDatabases().some(availableDatabase => {
+                if (
+                  availableDatabase.toLowerCase() ===
+                  statementDetails.precedingStatements[i].database.toLowerCase()
+                ) {
+                  self.database(availableDatabase);
+                  return true;
+                }
+              });
+              break;
+            }
+          }
           if (statementDetails.activeStatement) {
             self.positionStatement(statementDetails.activeStatement);
           } else {

+ 36 - 15
desktop/core/src/desktop/js/parse/jison/sqlStatementsParser.jison

@@ -41,7 +41,13 @@
 <singleQuote>'\''                                                     { this.popState(); return 'PART_OF_STATEMENT'; }
 
 '`'                                                                   { this.begin("backTick"); return 'PART_OF_STATEMENT'; }
-<backTick>[^`]+                                                       { return 'PART_OF_STATEMENT'; }
+<backTick>[^`]+                                                       {
+                                                                        if (parser.yy.usePreceding) {
+                                                                          parser.yy.useDatabase = yytext;
+                                                                          parser.yy.usePreceding = false;
+                                                                        }
+                                                                        return 'PART_OF_STATEMENT';
+                                                                      }
 <backTick><<EOF>>                                                     { this.popState(); return 'EOF'; }
 <backTick>'`'                                                         { this.popState(); return 'PART_OF_STATEMENT'; }
 
@@ -51,7 +57,17 @@
                                                                           if (firstWordMatch) {
                                                                             parser.yy.firstToken = firstWordMatch[0];
                                                                           }
-                                                                        };
+                                                                          var useDatabaseMatch = yytext.match(/USE\s+(\S+)/i);
+                                                                          if (useDatabaseMatch) {
+                                                                            parser.yy.useDatabase = useDatabaseMatch[1];
+                                                                          } else {
+                                                                            // For backticked
+                                                                            parser.yy.usePreceding = /USE/i.test(yytext);
+                                                                          }
+                                                                        } else if (parser.yy.usePreceding) {
+                                                                          parser.yy.useDatabase = yytext;
+                                                                          parser.yy.usePreceding = false;
+                                                                        }
                                                                         return 'PART_OF_STATEMENT';
                                                                       }
 [-][^;-]?                                                             { return 'PART_OF_STATEMENT'; }
@@ -108,22 +124,13 @@ SqlStatementsParser
 Statements
  : StatementParts
    {
-     if (parser.yy.firstToken) {
-       $$ = [{ type: 'statement', statement: $1, location: @1, firstToken: parser.yy.firstToken }];
-       parser.yy.firstToken = null;
-     } else {
-       $$ = [{ type: 'statement', statement: $1, location: @1 }];
-     }
+     $$ = [];
+     parser.addEntry($$, 'statement', $1, @1);
    }
  | Statements OneOrMoreSeparators StatementParts
    {
      parser.handleTrailingStatements($1, $2);
-     if (parser.yy.firstToken) {
-       $1.push({ type: 'statement', statement: $3, location: @3, firstToken: parser.yy.firstToken });
-       parser.yy.firstToken = null;
-     } else {
-       $1.push({ type: 'statement', statement: $3, location: @3 });
-     }
+     parser.addEntry($1, 'statement', $3, @3);
    }
  ;
 
@@ -142,6 +149,20 @@ OneOrMoreSeparators
 
 %%
 
+parser.addEntry = function (statements, type, statement, location) {
+  if (parser.yy.firstToken) {
+    if (parser.yy.useDatabase) {
+      statements.push({ type: type, statement: statement, location: location, firstToken: parser.yy.firstToken, database: parser.yy.useDatabase });
+      delete parser.yy.useDatabase;
+    } else {
+      statements.push({ type: type, statement: statement, location: location, firstToken: parser.yy.firstToken });
+    }
+    delete parser.yy.firstToken;
+  } else {
+    statements.push({ type: type, statement: statement, location: location });
+  }
+}
+
 parser.handleLeadingStatements = function (emptyStatements, result) {
   for (var i = emptyStatements.length - 1; i >= 0; i--) {
     result.unshift({ type: 'statement', statement: ';', location: emptyStatements[i] });
@@ -169,4 +190,4 @@ parser.removeTrailingWhiteSpace = function (result) {
   if (/^\s+$/.test(lastStatement.statement)) {
     result.pop()
   }
-}
+}

+ 22 - 1
desktop/core/src/desktop/js/parse/spec/sqlStatementsParserSpec.js

@@ -36,6 +36,9 @@ describe('sqlStatementsParser.js', () => {
       if (entry.firstToken) {
         s += ",\n  firstToken: '" + entry.firstToken + "'";
       }
+      if (entry.database) {
+        s += ",\n  database: '" + entry.database + "'";
+      }
       s += '\n}';
       first = false;
     });
@@ -371,7 +374,8 @@ describe('sqlStatementsParser.js', () => {
         {
           statement: 'USE `db;`;',
           location: { first_line: 1, first_column: 0, last_line: 1, last_column: 10 },
-          firstToken: 'USE'
+          firstToken: 'USE',
+          database: 'db;'
         },
         {
           statement: '\r\nSELECT " \\" ;; ", \'"\', \' ;\' from bla;',
@@ -385,4 +389,21 @@ describe('sqlStatementsParser.js', () => {
       ]
     );
   });
+
+  it('should find databases in use statements "-- commented USE statement\\nUSE boo;" correctly', () => {
+    testParser('-- commented USE statement\nUSE boo;/* USE baa; */use `foo`', [
+      {
+        statement: '-- commented USE statement\nUSE boo;',
+        location: { first_line: 1, first_column: 0, last_line: 2, last_column: 8 },
+        firstToken: 'USE',
+        database: 'boo'
+      },
+      {
+        statement: '/* USE baa; */use `foo`',
+        location: { first_line: 2, first_column: 8, last_line: 2, last_column: 31 },
+        firstToken: 'use',
+        database: 'foo'
+      }
+    ]);
+  });
 });

+ 37 - 15
desktop/core/src/desktop/js/parse/sqlStatementsParser.js

@@ -140,23 +140,14 @@ case 6:
 break;
 case 7:
 
-     if (parser.yy.firstToken) {
-       this.$ = [{ type: 'statement', statement: $$[$0], location: _$[$0], firstToken: parser.yy.firstToken }];
-       parser.yy.firstToken = null;
-     } else {
-       this.$ = [{ type: 'statement', statement: $$[$0], location: _$[$0] }];
-     }
+     this.$ = [];
+     parser.addEntry(this.$, 'statement', $$[$0], _$[$0]);
    
 break;
 case 8:
 
      parser.handleTrailingStatements($$[$0-2], $$[$0-1]);
-     if (parser.yy.firstToken) {
-       $$[$0-2].push({ type: 'statement', statement: $$[$0], location: _$[$0], firstToken: parser.yy.firstToken });
-       parser.yy.firstToken = null;
-     } else {
-       $$[$0-2].push({ type: 'statement', statement: $$[$0], location: _$[$0] });
-     }
+     parser.addEntry($$[$0-2], 'statement', $$[$0], _$[$0]);
    
 break;
 case 10:
@@ -328,6 +319,20 @@ parse: function parse(input) {
 }};
 
 
+parser.addEntry = function (statements, type, statement, location) {
+  if (parser.yy.firstToken) {
+    if (parser.yy.useDatabase) {
+      statements.push({ type: type, statement: statement, location: location, firstToken: parser.yy.firstToken, database: parser.yy.useDatabase });
+      delete parser.yy.useDatabase;
+    } else {
+      statements.push({ type: type, statement: statement, location: location, firstToken: parser.yy.firstToken });
+    }
+    delete parser.yy.firstToken;
+  } else {
+    statements.push({ type: type, statement: statement, location: location });
+  }
+}
+
 parser.handleLeadingStatements = function (emptyStatements, result) {
   for (var i = emptyStatements.length - 1; i >= 0; i--) {
     result.unshift({ type: 'statement', statement: ';', location: emptyStatements[i] });
@@ -355,7 +360,8 @@ parser.removeTrailingWhiteSpace = function (result) {
   if (/^\s+$/.test(lastStatement.statement)) {
     result.pop()
   }
-}/* generated by jison-lex 0.3.4 */
+}
+/* generated by jison-lex 0.3.4 */
 var lexer = (function(){
 var lexer = ({
 
@@ -719,7 +725,13 @@ case 16: this.popState(); return 8;
 break;
 case 17: this.begin("backTick"); return 8; 
 break;
-case 18: return 8; 
+case 18:
+                                                                        if (parser.yy.usePreceding) {
+                                                                          parser.yy.useDatabase = yy_.yytext;
+                                                                          parser.yy.usePreceding = false;
+                                                                        }
+                                                                        return 8;
+                                                                      
 break;
 case 19: this.popState(); return 5; 
 break;
@@ -731,7 +743,17 @@ case 21:
                                                                           if (firstWordMatch) {
                                                                             parser.yy.firstToken = firstWordMatch[0];
                                                                           }
-                                                                        };
+                                                                          var useDatabaseMatch = yy_.yytext.match(/USE\s+(\S+)/i);
+                                                                          if (useDatabaseMatch) {
+                                                                            parser.yy.useDatabase = useDatabaseMatch[1];
+                                                                          } else {
+                                                                            // For backticked
+                                                                            parser.yy.usePreceding = /USE/i.test(yy_.yytext);
+                                                                          }
+                                                                        } else if (parser.yy.usePreceding) {
+                                                                          parser.yy.useDatabase = yy_.yytext;
+                                                                          parser.yy.usePreceding = false;
+                                                                        }
                                                                         return 8;
                                                                       
 break;