瀏覽代碼

HUE-9070 [editor] Integrate primary keys info in the interface

Romain 6 年之前
父節點
當前提交
68605ed7a7

+ 1 - 0
apps/beeswax/src/beeswax/api.py

@@ -138,6 +138,7 @@ def _autocomplete(db, database=None, table=None, column=None, nested=None, query
       response['extended_columns'] = cols_extended
       response['extended_columns'] = cols_extended
       response['is_view'] = table.is_view
       response['is_view'] = table.is_view
       response['partition_keys'] = [{'name': part.name, 'type': part.type} for part in table.partition_keys]
       response['partition_keys'] = [{'name': part.name, 'type': part.type} for part in table.partition_keys]
+      response['primary_keys'] = [{'name': pk.name} for pk in table.primary_keys]
     else:
     else:
       col = db.get_column(database, table, column)
       col = db.get_column(database, table, column)
       if col:
       if col:

+ 4 - 3
apps/beeswax/src/beeswax/forms.py

@@ -120,9 +120,10 @@ class SaveResultsTableForm(forms.Form):
   """Used for saving the query result data to hive table"""
   """Used for saving the query result data to hive table"""
 
 
   target_table = common.HiveIdentifierField(
   target_table = common.HiveIdentifierField(
-                                  label=_t("Table Name"),
-                                  required=True,
-                                  help_text=_t("Name of the new table")) # Can also contain a DB prefixed table name, e.g. DB_NAME.TABLE_NAME
+      label=_t("Table Name"),
+      required=True,
+      help_text=_t("Name of the new table")
+  ) # Can also contain a DB prefixed table name, e.g. DB_NAME.TABLE_NAME
 
 
   def __init__(self, *args, **kwargs):
   def __init__(self, *args, **kwargs):
     self.db = kwargs.pop('db', None)
     self.db = kwargs.pop('db', None)

+ 2 - 2
apps/beeswax/src/beeswax/server/hive_server2_lib.py

@@ -141,13 +141,13 @@ class HiveServerTable(Table):
   def primary_keys(self):
   def primary_keys(self):
     rows = self.describe
     rows = self.describe
     try:
     try:
-      col_row_index = list(map(itemgetter('col_name'), rows)).index('# Primary Key') + 2
+      col_row_index = list(map(itemgetter('col_name'), rows)).index('# Primary Key') + 3
       keys = rows[col_row_index:]
       keys = rows[col_row_index:]
     except:
     except:
       # No info (e.g. IMPALA-8291)
       # No info (e.g. IMPALA-8291)
       keys = []
       keys = []
 
 
-    return [PartitionKeyCompatible(row['data_type'], 'NULL', row['comment']) for row in keys]
+    return [PartitionKeyCompatible(row['data_type'].strip(), 'NULL', row['comment']) for row in keys]
 
 
   @property
   @property
   def comment(self):
   def comment(self):

+ 1 - 1
apps/beeswax/src/beeswax/server/hive_server2_lib_tests.py

@@ -177,7 +177,7 @@ class TestHiveServerTable():
         columns=[
         columns=[
           # Dump of `DESCRIBE FORMATTED table`
           # Dump of `DESCRIBE FORMATTED table`
           Mock(stringVal=Mock(values=['# col_name', '', 'code', 'description', 'total_emp', 'salary', '', '# Partition Information', '# col_name', 'date', '', '# Detailed Table Information', 'Database:', 'OwnerType:', 'Owner:', 'CreateTime:', 'LastAccessTime:', 'Retention:', 'Location:', 'Table Type:', 'Table Parameters:', '', '', '', '', '', '', '', '', '', '', '# Storage Information', 'SerDe Library:', 'InputFormat:', 'OutputFormat:', 'Compressed:', 'Num Buckets:', 'Bucket Columns:', 'Sort Columns:', 'Storage Desc Params:', '', '', '# Constraints', '', '# Primary Key', 'Table:', 'Constraint Name:', 'Column Name:', 'Column Name:'], nulls='')),
           Mock(stringVal=Mock(values=['# col_name', '', 'code', 'description', 'total_emp', 'salary', '', '# Partition Information', '# col_name', 'date', '', '# Detailed Table Information', 'Database:', 'OwnerType:', 'Owner:', 'CreateTime:', 'LastAccessTime:', 'Retention:', 'Location:', 'Table Type:', 'Table Parameters:', '', '', '', '', '', '', '', '', '', '', '# Storage Information', 'SerDe Library:', 'InputFormat:', 'OutputFormat:', 'Compressed:', 'Num Buckets:', 'Bucket Columns:', 'Sort Columns:', 'Storage Desc Params:', '', '', '# Constraints', '', '# Primary Key', 'Table:', 'Constraint Name:', 'Column Name:', 'Column Name:'], nulls='')),
-          Mock(stringVal=Mock(values=['data_type', 'NULL', 'string', 'string', 'int', 'int', 'NULL', 'NULL', 'data_type', 'string', 'NULL', 'NULL', 'default', 'USER', 'hive', 'Mon Nov 04 07:44:10 PST 2019', 'UNKNOWN', '0', 'hdfs://nightly7x-unsecure-1.vpc.cloudera.com:8020/warehouse/tablespace/managed/hive/sample_07', 'MANAGED_TABLE', 'NULL', 'COLUMN_STATS_ACCURATE', 'bucketing_version', 'numFiles', 'numRows', 'rawDataSize', 'totalSize', 'transactional', 'transactional_properties', 'transient_lastDdlTime', 'NULL', 'NULL', 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe', 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat', 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat', 'No', '-1', '[]', '[]', 'NULL', 'serialization.format', 'NULL', 'NULL', 'NULL', 'default.pk', 'pk_165400321_1572980510006_0', 'id1', 'id2'], nulls='')),
+          Mock(stringVal=Mock(values=['data_type', 'NULL', 'string', 'string', 'int', 'int', 'NULL', 'NULL', 'data_type', 'string', 'NULL', 'NULL', 'default', 'USER', 'hive', 'Mon Nov 04 07:44:10 PST 2019', 'UNKNOWN', '0', 'hdfs://nightly7x-unsecure-1.vpc.cloudera.com:8020/warehouse/tablespace/managed/hive/sample_07', 'MANAGED_TABLE', 'NULL', 'COLUMN_STATS_ACCURATE', 'bucketing_version', 'numFiles', 'numRows', 'rawDataSize', 'totalSize', 'transactional', 'transactional_properties', 'transient_lastDdlTime', 'NULL', 'NULL', 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe', 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat', 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat', 'No', '-1', '[]', '[]', 'NULL', 'serialization.format', 'NULL', 'NULL', 'NULL', 'NULL', 'default.pk', 'pk_165400321_1572980510006_0', 'id1 ', 'id2 '], nulls='')),
           Mock(stringVal=Mock(values=['comment', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'comment', '', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', '{\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"code\":\"true\",\"description\":\"true\",\"salary\":\"true\",\"total_emp\":\"true\"}}', '2', '1', '822', '3288', '48445', 'true', 'insert_only', '1572882268', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', '1', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL'], nulls='')),
           Mock(stringVal=Mock(values=['comment', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'comment', '', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', '{\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"code\":\"true\",\"description\":\"true\",\"salary\":\"true\",\"total_emp\":\"true\"}}', '2', '1', '822', '3288', '48445', 'true', 'insert_only', '1572882268', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', '1', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL'], nulls='')),
         ]
         ]
       )
       )

+ 1 - 1
apps/search/src/search/tests.py

@@ -442,7 +442,7 @@ class TestWithMockedSolr(TestSearchBase):
          {'isDynamic': False, 'isId': None, 'type': 'string', 'name': 'content_type'},
          {'isDynamic': False, 'isId': None, 'type': 'string', 'name': 'content_type'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'description'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'description'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'features'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'features'},
-         {'isDynamic': False, 'isId': True, 'type': 'string', 'name': 'id'}
+         {'isDynamic': False, 'isId': True, 'type': 'string', 'name': 'id'},
          {'isDynamic': False, 'isId': None, 'type': 'boolean', 'name': 'inStock'},
          {'isDynamic': False, 'isId': None, 'type': 'boolean', 'name': 'inStock'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'includes'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'includes'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'keywords'},
          {'isDynamic': False, 'isId': None, 'type': 'text_general', 'name': 'keywords'},

+ 10 - 1
desktop/core/src/desktop/js/catalog/dataCatalogEntry.js

@@ -420,6 +420,12 @@ class DataCatalogEntry {
             partitionKeys[partitionKey.name] = true;
             partitionKeys[partitionKey.name] = true;
           });
           });
         }
         }
+        const primaryKeys = {};
+        if (sourceMeta.primary_keys) {
+          sourceMeta.primary_keys.forEach(primaryKey => {
+            primaryKeys[primaryKey.name] = true;
+          });
+        }
 
 
         const entities =
         const entities =
           sourceMeta.databases ||
           sourceMeta.databases ||
@@ -456,6 +462,9 @@ class DataCatalogEntry {
                       if (sourceMeta.partition_keys) {
                       if (sourceMeta.partition_keys) {
                         definition.partitionKey = !!partitionKeys[entity.name];
                         definition.partitionKey = !!partitionKeys[entity.name];
                       }
                       }
+                      if (sourceMeta.primary_keys) {
+                        definition.primaryKey = !!primaryKeys[entity.name];
+                      }
                       definition.index = index++;
                       definition.index = index++;
                       catalogEntry.definition = definition;
                       catalogEntry.definition = definition;
                       catalogEntry.saveLater();
                       catalogEntry.saveLater();
@@ -1230,7 +1239,7 @@ class DataCatalogEntry {
    */
    */
   isPrimaryKey() {
   isPrimaryKey() {
     const self = this;
     const self = this;
-    return self.isColumn() && self.definition && /true/i.test(self.definition.primary_key);
+    return self.isColumn() && self.definition && !!self.definition.primaryKey;
   }
   }
 
 
   /**
   /**

+ 2 - 0
desktop/libs/notebook/src/notebook/connectors/hiveserver2.py

@@ -865,10 +865,12 @@ DROP TABLE IF EXISTS `%(table)s`;
   def describe_table(self, notebook, snippet, database=None, table=None):
   def describe_table(self, notebook, snippet, database=None, table=None):
     db = self._get_db(snippet, self.interpreter)
     db = self._get_db(snippet, self.interpreter)
     tb = db.get_table(database, table)
     tb = db.get_table(database, table)
+
     return {
     return {
       'status': 0,
       'status': 0,
       'name': tb.name,
       'name': tb.name,
       'partition_keys': [{'name': part.name, 'type': part.type} for part in tb.partition_keys],
       'partition_keys': [{'name': part.name, 'type': part.type} for part in tb.partition_keys],
+      'primary_keys': [{'name': pk.name} for pk in tb.primary_keys],
       'cols': [{'name': col.name, 'type': col.type, 'comment': col.comment} for col in tb.cols],
       'cols': [{'name': col.name, 'type': col.type, 'comment': col.comment} for col in tb.cols],
       'path_location': tb.path_location,
       'path_location': tb.path_location,
       'hdfs_link': tb.hdfs_link,
       'hdfs_link': tb.hdfs_link,