فهرست منبع

HUE-6077 [editor] Show feedback on query hint computation and error

Only ON when optimizer is on for now as we dynamically change the selected statement.
We can see for ON by default when the parser is not confused in some multiqueries anymore.
Romain Rigaux 8 سال پیش
والد
کامیت
1d34d2b

+ 10 - 7
desktop/core/src/desktop/templates/assist.mako

@@ -1748,15 +1748,18 @@ from notebook.conf import get_ordered_interpreters
         <!-- ko if: HAS_OPTIMIZER -->
         <div class="assist-flex-header assist-divider"><div class="assist-inner-header">${ _('Suggestions') }</div></div>
         <div class="assist-flex-half">
-          <!-- ko if: !activeRisks().hints || activeRisks().hints.length === 0 -->
-          <div class="assist-no-entries">${ _('No optimization hints identified.') }</div>
+          <!-- ko if: ! activeRisks().hints -->
+          <div class="assist-no-entries">...</div>
           <!-- /ko -->
-          <!-- ko if: activeRisks().hints && activeRisks().hints.lenth > 0 -->
+          <!-- ko if: activeRisks().hints && activeRisks().hints.length === 0 -->
+          <div class="assist-no-entries">${ _('No optimizations identified.') }</div>
+          <!-- /ko -->
+          <!-- ko if: activeRisks().hints && activeRisks().hints.length > 0 -->
           <ul data-bind="foreach: activeRisks().hints">
             <li>
               <span data-bind="text: risk"></span>
               <span data-bind="text: riskAnalysis"></span>
-              <span data-bind="text: riskRecommendation"></span>
+              <div data-bind="text: riskRecommendation"></div>
             </li>
           </ul>
           <!-- /ko -->
@@ -1764,8 +1767,8 @@ from notebook.conf import get_ordered_interpreters
 
         <!-- ko if: hasActiveRisks() && activeRisks()['noDDL'].length > 0 -->
         <div class="assist-flex-fill">
-          <a href="javascript:void(0)" data-bind="visible: activeTables().length > 0, click: function() { huePubSub.publish('editor.table.stats.upload', activeTables()); }" title="${ _('Load table and columns DDL/stats in order to improve recommendations') }">
-            <i class="fa fa-fw fa-gears"></i> ${_('Optimize Analysis')}
+          <a href="javascript:void(0)" data-bind="visible: activeTables().length > 0, click: function() { huePubSub.publish('editor.table.stats.upload', activeTables()); }" title="${ _('Some table and columns DDL/stats are missing. Load them in order to improve the recommendations') }">
+            <i class="fa fa-fw fa-gears"></i> ${_('Optimize more')}
           </a>
         </div>
         <!-- /ko -->
@@ -1790,7 +1793,7 @@ from notebook.conf import get_ordered_interpreters
         self.activeColumns = ko.observableArray();
         self.activeRisks = ko.observable({});
         self.hasActiveRisks = ko.pureComputed(function () {
-           return Object.keys(self.activeRisks()).length > 0;
+           return self.activeRisks().hints && self.activeRisks().length > 0;
         });
         self.statementCount = ko.observable(0);
         self.activeStatementIndex = ko.observable(0);

+ 9 - 0
desktop/libs/metadata/src/metadata/navigator_client.py

@@ -79,6 +79,9 @@ class NavigatorApiException(Exception):
   def __init__(self, message=None):
     self.message = message or _('No error message, please check the logs.')
 
+  def __str__(self):
+    return str(self.message)
+
   def __unicode__(self):
     return smart_unicode(self.message)
 
@@ -87,6 +90,9 @@ class EntityDoesNotExistException(Exception):
   def __init__(self, message=None):
     self.message = message or _('No error message, please check the logs.')
 
+  def __str__(self):
+    return str(self.message)
+
   def __unicode__(self):
     return smart_unicode(self.message)
 
@@ -95,6 +101,9 @@ class NavigathorAuthException(Exception):
   def __init__(self, message=None):
     self.message = message or _('No error message, please check the logs.')
 
+  def __str__(self):
+    return str(self.message)
+
   def __unicode__(self):
     return smart_unicode(self.message)
 

+ 4 - 1
desktop/libs/metadata/src/metadata/optimizer_client.py

@@ -45,6 +45,9 @@ class NavOptException(Exception):
   def __init__(self, message=None):
     self.message = message or _('No error message, please check the logs.')
 
+  def __str__(self):
+    return str(self.message)
+
   def __unicode__(self):
     return smart_unicode(self.message)
 
@@ -179,7 +182,7 @@ class OptimizerApi(object):
 
     hints = response.get(source_platform + 'Risk', {})
 
-    if hints and hints == [{u'riskAnalysis': u'', u'risk': u'low', u'riskId': 0, u'riskRecommendation': u''}]:
+    if hints and hints == [{"riskTables": [], "riskAnalysis": "", "riskId": 0, "risk": "low", "riskRecommendation": ""}]:
       hints = []
 
     return {

+ 5 - 25
desktop/libs/metadata/src/metadata/optimizer_client_tests.py

@@ -310,26 +310,6 @@ FROM
 
 
   def test_risk_cartesian_cross_join(self):
-    source_platform = 'hive'
-    query = '''SELECT s07.description, s07.total_emp, s08.total_emp, s07.salary
-FROM
-  sample_07 s07
-
-CROSS
-
-JOIN
-  sample_08 s08
-ON ( s07.code = s08.code )
-WHERE
-( s07.total_emp > s08.total_emp
- AND s07.salary > 100000 )
-ORDER BY s07.salary DESC
-'''
-
-    resp = self.api.query_risk(query=query, source_platform=source_platform, db_name='default')
-    _assert_risks(['Cartesian or CROSS join found.'], resp['hints'])
-
-
     source_platform = 'hive'
     query = '''SELECT ID, NAME, AMOUNT, DATE FROM CUSTOMERS, ORDERS
 '''
@@ -425,34 +405,34 @@ LIMIT 1000
     db_name = 'default'
 
     resp = self.api.query_risk(query=query, source_platform=source_platform, db_name=db_name)
-    _assert_risks(['Query on partitioned table is missing filters on parttioning columns.'], resp['hints'])
+    _assert_risks(['Query on partitioned table is missing filters on partioning columns.'], resp['hints'])
 
 
     source_platform = 'hive'
     query = '''SELECT * FROM web_logs LIMIT 1'''
 
     resp = self.api.query_risk(query=query, source_platform=source_platform, db_name=db_name)
-    _assert_risks(['Query on partitioned table is missing filters on parttioning columns.'], resp['hints'])
+    _assert_risks(['Query on partitioned table is missing filters on partioning columns.'], resp['hints'])
 
 
     source_platform = 'hive'
     query = '''SELECT * FROM web_logs WHERE app='oozie' LIMIT 1'''
 
     resp = self.api.query_risk(query=query, source_platform=source_platform, db_name=db_name)
-    _assert_risks(['Query on partitioned table is missing filters on parttioning columns.'], resp['hints'])
+    _assert_risks(['Query on partitioned table is missing filters on partioning columns.'], resp['hints'])
 
 
     source_platform = 'hive'
     query = '''SELECT * FROM web_logs WHERE date='20180101' '''
 
     resp = self.api.query_risk(query=query, source_platform=source_platform, db_name=db_name)
-    _assert_risks(['Query on partitioned table is missing filters on parttioning columns.'], resp['hints'], present=False)
+    _assert_risks(['Query on partitioned table is missing filters on partioning columns.'], resp['hints'], present=False)
 
     source_platform = 'hive'
     query = '''SELECT * FROM web_logs WHERE app='oozie' AND date='20180101' '''
 
     resp = self.api.query_risk(query=query, source_platform=source_platform, db_name=db_name)
-    _assert_risks(['Query on partitioned table is missing filters on parttioning columns.'], resp['hints'], present=False)
+    _assert_risks(['Query on partitioned table is missing filters on partioning columns.'], resp['hints'], present=False)
 
 
 def _assert_risks(risks, suggestions, present=True):

+ 9 - 6
desktop/libs/notebook/src/notebook/static/notebook/js/notebook.ko.js

@@ -511,6 +511,7 @@ var EditorViewModel = (function() {
     });
     self.statement_raw = ko.observable(typeof snippet.statement_raw != "undefined" && snippet.statement_raw != null ? snippet.statement_raw : '');
     self.selectedStatement = ko.observable('');
+    self.positionStatement = ko.observable('');
     self.aceSize = ko.observable(typeof snippet.aceSize != "undefined" && snippet.aceSize != null ? snippet.aceSize : 100);
     // self.statement_raw.extend({ rateLimit: 150 }); // Should prevent lag from typing but currently send the old query when using the key shortcut
     self.status = ko.observable(typeof snippet.status != "undefined" && snippet.status != null ? snippet.status : 'loading');
@@ -603,7 +604,7 @@ var EditorViewModel = (function() {
       }
     });
     self.statement = ko.computed(function () {
-      var statement = self.isSqlDialect() && self.selectedStatement() ? self.selectedStatement() : self.statement_raw();
+      var statement = self.isSqlDialect() ? (self.selectedStatement() ? self.selectedStatement() : (self.positionStatement() && HAS_OPTIMIZER ? self.positionStatement() : self.statement_raw())) : self.statement_raw();
       $.each(self.variables(), function (index, variable) {
         statement = statement.replace(RegExp("([^\\\\])?\\${" + variable.name() + "}", "g"), "$1" + variable.value());
       });
@@ -894,7 +895,7 @@ var EditorViewModel = (function() {
       self.delayedStatement = ko.pureComputed(self.statement).extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 2000 } });
 
       self.checkComplexity = function () {
-        if (lastCheckedComplexityStatement === self.statement_raw()) {
+        if (lastCheckedComplexityStatement === self.statement()) {
           return;
         }
 
@@ -902,6 +903,8 @@ var EditorViewModel = (function() {
 
         hueAnalytics.log('notebook', 'get_query_risk');
         self.complexityCheckRunning(true);
+        self.hasSuggestion(null);
+        self.complexity({});
         huePubSub.publish('editor.active.risks', {});
 
         lastComplexityRequest = $.ajax({
@@ -917,11 +920,11 @@ var EditorViewModel = (function() {
               self.complexity(data.query_complexity);
               self.hasSuggestion('');
             } else {
-              self.hasSuggestion(data.message); // TODO Properly inform user
-              self.complexity({});
+              self.hasSuggestion('error');
+              self.complexity({'hints': []});
             }
             huePubSub.publish('editor.active.risks', self.complexity());
-            lastCheckedComplexityStatement = self.statement_raw();
+            lastCheckedComplexityStatement = self.statement();
             self.complexityCheckRunning(false);
           }
         });
@@ -1122,7 +1125,7 @@ var EditorViewModel = (function() {
             if (vm.isNotificationManager()) { // Update task status
               var tasks = $.grep(notebook.history(), function(row) { return row.uuid() == notebook.uuid()});
               if (tasks.length == 1) {
-                tasks[0].status(self.status()); console.log(tasks[0].uuid());
+                tasks[0].status(self.status());
               }
             } else {
               notebook.history.unshift(

+ 11 - 0
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -1059,6 +1059,14 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, ENABLE_
         <span class="optimizer-explanation alert-success alert-neutral">${ _('Query validated.') }</span>
       <!-- /ko -->
     <!-- /ko -->
+    <!-- ko if: hasSuggestion() == 'error'  -->
+      <div class="round-icon success" data-bind="click: function(){ showOptimizer(! showOptimizer()) }, attr: { 'title': showOptimizer() ? '${ _ko('Close Validator') }' : '${ _ko('Open Validator') }'}">
+        <i class="fa fa-check"></i>
+      </div>
+      <!-- ko if: showOptimizer -->
+        <span class="optimizer-explanation alert-neutral alert-neutral">${ _('Not validated.') }</span>
+      <!-- /ko -->
+    <!-- /ko -->
   </div>
   <!-- /ko -->
 
@@ -3063,6 +3071,9 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, ENABLE_
         viewModel.selectedNotebook().snippets()[0].loadQueryHistory(100);
       });
 
+      huePubSub.subscribe('active.editor.statement.changed', function (statement) {
+        viewModel.selectedNotebook().snippets()[0].positionStatement(statement);
+      });
 
       var isAssistAvailable = viewModel.assistAvailable();
       var wasAssistVisible = viewModel.isLeftPanelVisible();