Browse Source

HUE-3228 [dashboard] Non hardcoded backticks

Postgresql works with double quotes
Romain 6 years ago
parent
commit
39367d4271
1 changed files with 81 additions and 39 deletions
  1. 81 39
      desktop/libs/notebook/src/notebook/dashboard_api.py

+ 81 - 39
desktop/libs/notebook/src/notebook/dashboard_api.py

@@ -52,6 +52,8 @@ class SQLDashboardApi(DashboardApi):
     self.engine = engine
     self.engine = engine
     self.source = source
     self.source = source
     self.async = engine == 'hive' or engine == 'impala'
     self.async = engine == 'hive' or engine == 'impala'
+    self.backticks = '"' if engine == 'postgresql' else '`'
+
 
 
   def query(self, dashboard, query, facet=None):
   def query(self, dashboard, query, facet=None):
     if query['qs'] == [{'q': '_root_:*'}]:
     if query['qs'] == [{'q': '_root_:*'}]:
@@ -70,9 +72,10 @@ class SQLDashboardApi(DashboardApi):
       database, table = '', ''
       database, table = '', ''
     else:
     else:
       database, table = self._get_database_table_names(dashboard['name'])
       database, table = self._get_database_table_names(dashboard['name'])
-      sql_from = '`%(database)s`.`%(table)s`' % {
+      sql_from = '%(backticks)s%(database)s%(backticks)s.%(backticks)s%(table)s%(backticks)s' % {
         'database': database,
         'database': database,
-        'table': table
+        'table': table,
+        'backticks': self.backticks
       }
       }
 
 
     if facet and facet['properties']['facets']:
     if facet and facet['properties']['facets']:
@@ -158,7 +161,15 @@ class SQLDashboardApi(DashboardApi):
         result_properties = facet['properties']['result']
         result_properties = facet['properties']['result']
     else:
     else:
       fields = Collection2.get_field_list(dashboard)
       fields = Collection2.get_field_list(dashboard)
-      order_by = ', '.join(['`%s` %s' % (f['name'], f['sort']['direction']) for f in dashboard['template']['fieldsAttributes'] if f['sort']['direction'] and f['name'] in fields])
+      order_by = ', '.join([
+        '%(backticks)s%(name)s%(backticks)s %(direction)s' % {
+            'backticks': self.backticks,
+            'name': f['name'],
+            'direction': f['sort']['direction']
+          }
+          for f in dashboard['template']['fieldsAttributes'] if f['sort']['direction'] and f['name'] in fields
+        ]
+      )
       sql = '''
       sql = '''
       SELECT %(fields)s
       SELECT %(fields)s
       FROM %(sql_from)s
       FROM %(sql_from)s
@@ -166,7 +177,12 @@ class SQLDashboardApi(DashboardApi):
       %(order_by)s
       %(order_by)s
       %(limit)s''' % {
       %(limit)s''' % {
           'sql_from': sql_from,
           'sql_from': sql_from,
-          'fields': ', '.join(['`%s` as `%s`' % (f, f) if f != '*' else '*' for f in fields]),
+          'fields': ', '.join([
+            '%(backticks)s%(column)s%(backticks)s as %(backticks)s%(column)s%(backticks)s' % {
+              'backticks': self.backticks,
+              'column': f
+            } if f != '*' else '*' for f in fields
+          ]),
           'filters': self._convert_filters_to_where(filters) if filters else '',
           'filters': self._convert_filters_to_where(filters) if filters else '',
           'order_by': 'ORDER BY %s' % order_by if order_by else '',
           'order_by': 'ORDER BY %s' % order_by if order_by else '',
           'limit': 'LIMIT %s' % dashboard['template']['rows'] or LIMIT
           'limit': 'LIMIT %s' % dashboard['template']['rows'] or LIMIT
@@ -268,10 +284,16 @@ class SQLDashboardApi(DashboardApi):
 
 
     # TODO: check column stats to go faster
     # TODO: check column stats to go faster
 
 
-    sql = "SELECT MIN(`%(field)s`), MAX(`%(field)s`) FROM `%(database)s`.`%(table)s`" % {
-      'field': fields[0],
-      'database': database,
-      'table': table
+    sql = '''
+      SELECT
+        MIN(%(backticks)s%(field)s%(backticks)s),
+        MAX(%(backticks)s%(field)s%(backticks)s)
+      FROM %(backticks)s%(database)s%(backticks)s.%(backticks)s%(table)s%(backticks)s
+    ''' % {
+        'field': fields[0],
+        'database': database,
+        'table': table,
+        'backticks': self.backticks
     }
     }
 
 
     result = self._sync_execute(sql, database)
     result = self._sync_execute(sql, database)
@@ -301,12 +323,17 @@ class SQLDashboardApi(DashboardApi):
     field = self._get_field(dashboard, dashboard['idField'])
     field = self._get_field(dashboard, dashboard['idField'])
     quotes = '' if self._is_number(field['type']) else "'"
     quotes = '' if self._is_number(field['type']) else "'"
 
 
-    sql = "SELECT * FROM `%(database)s`.`%(table)s` WHERE `%(idField)s` = %(quotes)s%(doc_id)s%(quotes)s" % {
-      'database': database,
-      'table': table,
-      'idField': dashboard['idField'], # Only 1 PK currently,
-      'doc_id': doc_id,
-      'quotes': quotes
+    sql = '''
+        SELECT *
+        FROM %(backticks)s%(database)s%(backticks)s.%(backticks)s%(table)s%(backticks)s
+        WHERE %(backticks)s%(idField)s%(backticks)s = %(quotes)s%(doc_id)s%(quotes)s
+    '''  % {
+        'database': database,
+        'table': table,
+        'idField': dashboard['idField'], # Only 1 PK currently,
+        'doc_id': doc_id,
+        'quotes': quotes,
+        'backticks': self.backticks
     }
     }
 
 
     result = self._sync_execute(sql, database)
     result = self._sync_execute(sql, database)
@@ -431,11 +458,16 @@ class SQLDashboardApi(DashboardApi):
             quote = "'"
             quote = "'"
           else:
           else:
             quote = ''
             quote = ''
-          clauses.append("`%(field)s` >= %(quote)s%(from)s%(quote)s AND `%(field)s` < %(quote)s%(to)s%(quote)s" % {
-            'field': fq['field'],
-            'to': fq['properties'][0]['to'],
-            'from': fq['properties'][0]['from'],
-            'quote': quote
+          clauses.append(
+            '''
+              %(backticks)s%(field)s%(backticks)s >= %(quote)s%(from)s%(quote)s AND
+              %(backticks)s%(field)s%(backticks)s < %(quote)s%(to)s%(quote)s
+            ''' % {
+              'field': fq['field'],
+              'to': fq['properties'][0]['to'],
+              'from': fq['properties'][0]['from'],
+              'quote': quote,
+              'backticks': self.backticks
           })
           })
       elif fq['type'] == 'map':
       elif fq['type'] == 'map':
         for direction in ['lat', 'lon']:
         for direction in ['lat', 'lon']:
@@ -445,20 +477,25 @@ class SQLDashboardApi(DashboardApi):
               quote = ''
               quote = ''
             else:
             else:
               quote = "'"
               quote = "'"
-            min_direction = min(fq['properties'][direction+'_sw'], fq['properties'][direction+'_ne'])
-            max_direction = max(fq['properties'][direction+'_sw'], fq['properties'][direction+'_ne'])
-            clauses.append("`%(field)s` >= %(quote)s%(from)s%(quote)s AND `%(field)s` < %(quote)s%(to)s%(quote)s" % {
-              'field': fq[direction],
-              'to': max_direction,
-              'from': min_direction,
-              'quote': quote
+            min_direction = min(fq['properties'][direction+'_sw'], fq['properties'][direction + '_ne'])
+            max_direction = max(fq['properties'][direction+'_sw'], fq['properties'][direction + '_ne'])
+            clauses.append('''
+                %(backticks)s%(field)s%(backticks)s >= %(quote)s%(from)s%(quote)s AND
+                %(backticks)s%(field)s%(backticks)s < %(quote)s%(to)s%(quote)s
+              ''' % {
+                'field': fq[direction],
+                'to': max_direction,
+                'from': min_direction,
+                'quote': quote,
+                'backticks': self.backticks
             })
             })
     return clauses
     return clauses
 
 
   def _get_field_condition_formatting(self, table, facet, field_name):
   def _get_field_condition_formatting(self, table, facet, field_name):
     field = self._get_field(table, field_name, facet=facet)
     field = self._get_field(table, field_name, facet=facet)
     if field:
     if field:
-      return "`%s` %s %s" if self._is_number(field['type']) else "`%s` %s '%s'"
+      column = self.backticks + "%s" + self.backticks + ' '
+      return column + ("%s %s" if self._is_number(field['type']) else "%s '%s'")
     else:
     else:
       return ''
       return ''
 
 
@@ -481,7 +518,8 @@ class SQLDashboardApi(DashboardApi):
         fields.append(facet['field'])
         fields.append(facet['field'])
     elif facet['aggregate']['function'] == 'unique':
     elif facet['aggregate']['function'] == 'unique':
       facet['aggregate']['function'] = 'COUNT'
       facet['aggregate']['function'] = 'COUNT'
-      fields.append('distinct `%(field)s`' % facet)
+      facet['backticks'] = self.backticks
+      fields.append('distinct %(backticks)s%(field)s%(backticks)s' % facet)
     elif facet['aggregate']['function'] == 'percentile':
     elif facet['aggregate']['function'] == 'percentile':
       if cls._supports_percentile():
       if cls._supports_percentile():
         fields.append('%s, %s' % (facet['field'], cls._zero_to_one(float(facet['aggregate']['percentile']))))
         fields.append('%s, %s' % (facet['field'], cls._zero_to_one(float(facet['aggregate']['percentile']))))
@@ -527,20 +565,21 @@ class SQLDashboardApi(DashboardApi):
 
 
     if facet['canRange']:
     if facet['canRange']:
       field_name = '%(field)s_range' % facet
       field_name = '%(field)s_range' % facet
-      order_by = '`%(field)s_range_%(position)s` %(sort)s' % facet
+      facet['backticks'] = self.backticks
+      order_by = '%(backticks)s%(field)s_range_%(position)s%(backticks)s %(sort)s' % facet
       if facet['isDate']:
       if facet['isDate']:
-        field = '`%(field)s`' % facet
+        field = '%(backticks)s%(field)s%(backticks)s' % facet
 
 
         slot = self._gap_to_units(facet['gap'])
         slot = self._gap_to_units(facet['gap'])
 
 
         if slot['unit'] != 'SECOND':
         if slot['unit'] != 'SECOND':
           select = """
           select = """
-            trunc(%(field)s, '%(slot)s') AS `%(field_name)s_%(position)s`,
-            trunc(%(field)s, '%(slot)s') + interval %(slot_interval)s AS `%(field_name)s_to_%(position)s`"""
+            trunc(%(field)s, '%(slot)s') AS %(backticks)s%(field_name)s_%(position)s%(backticks)s,
+            trunc(%(field)s, '%(slot)s') + interval %(slot_interval)s AS %(backticks)s%(field_name)s_to_%(position)s%(backticks)s"""
         else:
         else:
           select = """
           select = """
-            %(field)s AS `%(field_name)s_%(position)s`,
-            %(field)s + interval %(slot_interval)s AS `%(field_name)s_to_%(position)s`"""
+            %(field)s AS %(backticks)s%(field_name)s_%(position)s%(backticks)s,
+            %(field)s + interval %(slot_interval)s AS %(backticks)s%(field_name)s_to_%(position)s%(backticks)s"""
         select = select % {
         select = select % {
             'field': field,
             'field': field,
             'slot': slot['sql_trunc'],
             'slot': slot['sql_trunc'],
@@ -548,17 +587,19 @@ class SQLDashboardApi(DashboardApi):
             'field_name': field_name,
             'field_name': field_name,
             'start': facet['start'],
             'start': facet['start'],
             'end': facet['end'],
             'end': facet['end'],
-            'position': facet['position']
+            'position': facet['position'],
+            'backticks': self.backticks
         }
         }
       else:
       else:
         slot = facet['gap']
         slot = facet['gap']
         select = """
         select = """
-        floor(floor((`%(field)s` - %(start)s) / %(slot)s) * %(slot)s) + %(start)s AS `%(field_name)s_%(position)s`""" % { # Beware: start might be not in sync with the UI
+        floor(floor((%(backticks)s%(field)s%(backticks)s - %(start)s) / %(slot)s) * %(slot)s) + %(start)s AS %(backticks)s%(field_name)s_%(position)s%(backticks)s""" % { # Beware: start might be not in sync with the UI
           'field': facet['field'],
           'field': facet['field'],
           'slot': slot,
           'slot': slot,
           'field_name': field_name,
           'field_name': field_name,
           'start': facet['start'],
           'start': facet['start'],
-          'position': facet['position']
+          'position': facet['position'],
+          'backticks': self.backticks
         }
         }
     else:
     else:
       field_name = '%(field)s' % facet
       field_name = '%(field)s' % facet
@@ -566,7 +607,7 @@ class SQLDashboardApi(DashboardApi):
       order_by = '%(field)s_%(position)s %(sort)s' % facet
       order_by = '%(field)s_%(position)s %(sort)s' % facet
 
 
     return {
     return {
-      'name': '`%s`' % field_name,
+      'name': '%(backticks)s%(field)s%(backticks)s' % {'backticks': self.backticks, 'field': field_name},
       'select': select,
       'select': select,
       'order_by': order_by
       'order_by': order_by
     }
     }
@@ -665,7 +706,8 @@ class SQLDashboardApi(DashboardApi):
     props = self._get_time_filter_range(collection, query)
     props = self._get_time_filter_range(collection, query)
 
 
     if props:
     if props:
-      return "(`%(field)s` >= %(from)s AND `%(field)s` <= %(to)s)" %  props
+      props['backticks'] = self.backticks
+      return "(%(backticks)s%(field)s%(backticks)s >= %(from)s AND %(backticks)s%(field)s%(backticks)s <= %(to)s)" %  props
     else:
     else:
       return {}
       return {}