Ver código fonte

HUE-9454 [editor] Use the identifier escape char from the connector properties in the editor

Johan Ahlen 5 anos atrás
pai
commit
09ae1da0bc

+ 1 - 1
desktop/core/src/desktop/js/ko/bindings/ace/aceLocationHandler.js

@@ -1096,7 +1096,7 @@ class AceLocationHandler {
               const uniqueValues = [];
               for (let i = 0; i < possibleValues.length; i++) {
                 possibleValues[i].name = sqlUtils.backTickIfNeeded(
-                  self.dialect(),
+                  self.snippet.connector(),
                   possibleValues[i].name
                 );
                 const nameLower = possibleValues[i].name.toLowerCase();

+ 2 - 2
desktop/core/src/desktop/js/ko/components/assist/assistDbEntry.js

@@ -25,7 +25,7 @@ const findNameInHierarchy = (entry, searchCondition) => {
     entry = entry.parent;
   }
   if (entry) {
-    return sqlUtils.backTickIfNeeded(entry.catalogEntry.getDialect(), entry.catalogEntry.name);
+    return sqlUtils.backTickIfNeeded(entry.catalogEntry.getConnector(), entry.catalogEntry.name);
   }
 };
 
@@ -221,7 +221,7 @@ class AssistDbEntry {
           parts.push('[]');
         }
       } else {
-        parts.push(sqlUtils.backTickIfNeeded(sourceType, entry.catalogEntry.name));
+        parts.push(sqlUtils.backTickIfNeeded(entry.getConnector(), entry.catalogEntry.name));
         parts.push('.');
       }
       entry = entry.parent;

+ 6 - 6
desktop/core/src/desktop/js/ko/components/assist/ko.assistDbPanel.js

@@ -166,7 +166,7 @@ const ASSIST_TABLE_TEMPLATES = `
           'Open'
         )}"></i></a>
       </div>
-      <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': catalogEntry.getTitle(true) }, draggableText: { text: editorText,  meta: {'type': 'sql', 'isView': catalogEntry.isView(), 'table': tableName, 'database': databaseName} }">
+      <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': catalogEntry.getTitle(true) }, draggableText: { text: editorText,  meta: { connector: catalogEntry.getConnector(), type: 'sql', isView: catalogEntry.isView(), table: tableName, database: databaseName } }">
         <i class="fa fa-fw muted valign-middle" data-bind="css: iconClass"></i>
         <span class="highlightable" data-bind="text: catalogEntry.getDisplayName(navigationSettings.rightAssist), css: { 'highlight': highlight }"></span>
       </a>
@@ -184,12 +184,12 @@ const ASSIST_TABLE_TEMPLATES = `
       </div>
       <!-- ko if: expandable -->
       <a class="assist-entry assist-field-link" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': catalogEntry.getTitle(true) }, css: { 'assist-entry-left-action': navigationSettings.rightAssist }">
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: { connector: catalogEntry.getConnector(), type: 'sql', column: columnName, table: tableName, database: databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
       </a>
       <!-- /ko -->
       <!-- ko ifnot: expandable -->
       <div class="assist-entry assist-field-link default-cursor" href="javascript:void(0)" data-bind="event: { dblclick: dblClick }, attr: {'title': catalogEntry.getTitle(true) }, css: { 'assist-entry-left-action': navigationSettings.rightAssist }">
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: { connector: catalogEntry.getConnector(), type: 'sql', column: columnName, table: tableName, database: databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
       </div>
       <!-- /ko -->
       <div class="center assist-spinner" data-bind="visible: loading"><i class="fa fa-spinner fa-spin"></i></div>
@@ -207,13 +207,13 @@ const ASSIST_TABLE_TEMPLATES = `
       <!-- ko if: expandable -->
       <a class="assist-entry assist-field-link assist-field-link-dark assist-entry-left-action assist-ellipsis" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': catalogEntry.getTitle(true) }">
         <span data-bind="text: catalogEntry.getType()" class="muted pull-right margin-right-20"></span>
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.name, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: { 'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.name, draggableText: { text: editorText, meta: { connector: catalogEntry.getConnector(), type: 'sql', column: columnName, table: tableName, database: databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
       </a>
       <!-- /ko -->
       <!-- ko ifnot: expandable -->
       <div class="assist-entry assist-field-link assist-field-link-dark default-cursor assist-ellipsis" href="javascript:void(0)" data-bind="event: { dblclick: dblClick }, attr: {'title': catalogEntry.getTitle(true) }, css: { 'assist-entry-left-action': navigationSettings.rightAssist }">
         <span data-bind="text: catalogEntry.getType()" class="muted pull-right margin-right-20"></span>
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.name, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.name, draggableText: { text: editorText, meta: { connector: catalogEntry.getConnector(), type: 'sql', column: columnName, table: tableName, database: databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT}', params: { entry: catalogEntry } } --><!-- /ko --><!-- /ko -->
       </div>
       <!-- /ko -->
       <div class="center assist-spinner" data-bind="visible: loading"><i class="fa fa-spinner fa-spin"></i></div>
@@ -282,7 +282,7 @@ const TEMPLATE =
   <script type="text/html" id="assist-database-entry">
     <li class="assist-table" data-bind="appAwareTemplateContextMenu: { template: 'sql-context-items', scrollContainer: '.assist-db-scrollable' }, visibleOnHover: { selector: '.database-actions' }">
       <!-- ko template: { name: 'assist-database-actions' } --><!-- /ko -->
-      <a class="assist-table-link" href="javascript: void(0);" data-bind="click: function () { $parent.selectedDatabase($data); $parent.selectedDatabaseChanged(); }, attr: {'title': catalogEntry.getTitle(true) }, draggableText: { text: editorText,  meta: {'type': 'sql', 'database': databaseName} }"><i class="fa fa-fw fa-database muted valign-middle"></i> <span class="highlightable" data-bind="text: catalogEntry.name, css: { 'highlight': highlight() }"></span></a>
+      <a class="assist-table-link" href="javascript: void(0);" data-bind="click: function () { $parent.selectedDatabase($data); $parent.selectedDatabaseChanged(); }, attr: {'title': catalogEntry.getTitle(true) }, draggableText: { text: editorText,  meta: { connector: catalogEntry.getConnector(), type: 'sql', database: databaseName } }"><i class="fa fa-fw fa-database muted valign-middle"></i> <span class="highlightable" data-bind="text: catalogEntry.name, css: { 'highlight': highlight() }"></span></a>
     </li>
   </script>
 

+ 9 - 9
desktop/core/src/desktop/js/ko/components/contextPopover/asteriskContextTabs.js

@@ -23,7 +23,7 @@ import I18n from 'utils/i18n';
 import sqlUtils from 'sql/sqlUtils';
 
 class AsteriskData {
-  constructor(data, sourceType, namespace, compute, defaultDatabase) {
+  constructor(data, connector, namespace, compute, defaultDatabase) {
     const self = this;
     self.loading = ko.observable(true);
     self.hasErrors = ko.observable(false);
@@ -64,19 +64,19 @@ class AsteriskData {
         text: $.map(colsToExpand, column => {
           if (column.tableAlias) {
             return (
-              sqlUtils.backTickIfNeeded(sourceType, column.tableAlias) +
+              sqlUtils.backTickIfNeeded(connector, column.tableAlias) +
               '.' +
-              sqlUtils.backTickIfNeeded(sourceType, column.name)
+              sqlUtils.backTickIfNeeded(connector, column.name)
             );
           }
           if (colIndex[column.name]) {
             return (
-              sqlUtils.backTickIfNeeded(sourceType, column.table) +
+              sqlUtils.backTickIfNeeded(connector, column.table) +
               '.' +
-              sqlUtils.backTickIfNeeded(sourceType, column.name)
+              sqlUtils.backTickIfNeeded(connector, column.name)
             );
           }
-          return sqlUtils.backTickIfNeeded(sourceType, column.name);
+          return sqlUtils.backTickIfNeeded(connector, column.name);
         }).join(', ')
       });
       huePubSub.publish('context.popover.hide');
@@ -97,7 +97,7 @@ class AsteriskData {
           .getEntry({
             namespace: namespace,
             compute: compute,
-            connector: { id: sourceType }, // TODO: Add connector to asteriskContextTabs
+            connector: connector,
             path: path
           })
           .done(entry => {
@@ -152,9 +152,9 @@ class AsteriskData {
 }
 
 class AsteriskContextTabs {
-  constructor(data, sourceType, namespace, compute, defaultDatabase) {
+  constructor(data, connector, namespace, compute, defaultDatabase) {
     const self = this;
-    self.data = new AsteriskData(data, sourceType, namespace, compute, defaultDatabase);
+    self.data = new AsteriskData(data, connector, namespace, compute, defaultDatabase);
 
     self.tabs = [
       {

+ 1 - 1
desktop/core/src/desktop/js/ko/components/contextPopover/ko.contextPopover.js

@@ -730,7 +730,7 @@ class ContextPopoverViewModel {
     } else if (self.isAsterisk) {
       self.contents = new AsteriskContextTabs(
         self.data,
-        self.sourceType,
+        self.connector,
         self.namespace,
         self.compute,
         self.defaultDatabase

+ 2 - 2
desktop/core/src/desktop/js/ko/components/ko.editorDroppableMenu.js

@@ -67,9 +67,9 @@ class EditorDroppableMenu extends DisposableComponent {
       const meta = this.meta();
       if (meta && meta.database && meta.table) {
         return (
-          sqlUtils.backTickIfNeeded(meta.type, meta.database) +
+          sqlUtils.backTickIfNeeded(meta.connector, meta.database) +
           '.' +
-          sqlUtils.backTickIfNeeded(meta.type, meta.table)
+          sqlUtils.backTickIfNeeded(meta.connector, meta.table)
         );
       }
       return '';

+ 13 - 10
desktop/core/src/desktop/js/sql/autocompleteResults.js

@@ -897,7 +897,7 @@ class AutocompleteResults {
             databaseSuggestions.push({
               value:
                 prefix +
-                sqlUtils.backTickIfNeeded(self.dialect(), dbEntry.name) +
+                sqlUtils.backTickIfNeeded(self.snippet.connector(), dbEntry.name) +
                 (suggestDatabases.appendDot ? '.' : ''),
               filterValue: dbEntry.name,
               meta: META_I18n.database,
@@ -956,7 +956,9 @@ class AutocompleteResults {
                       return;
                     }
                     tableSuggestions.push({
-                      value: prefix + sqlUtils.backTickIfNeeded(self.dialect(), tableEntry.name),
+                      value:
+                        prefix +
+                        sqlUtils.backTickIfNeeded(self.snippet.connector(), tableEntry.name),
                       filterValue: tableEntry.name,
                       tableName: tableEntry.name,
                       meta: META_I18n[tableEntry.getType().toLowerCase()],
@@ -1102,7 +1104,7 @@ class AutocompleteResults {
                 typeof column.type !== 'undefined' && column.type !== 'COLREF' ? column.type : 'T';
               if (typeof column.alias !== 'undefined') {
                 columnSuggestions.push({
-                  value: sqlUtils.backTickIfNeeded(self.dialect(), column.alias),
+                  value: sqlUtils.backTickIfNeeded(self.snippet.connector(), column.alias),
                   filterValue: column.alias,
                   meta: type,
                   category: CATEGORIES.COLUMN,
@@ -1118,7 +1120,7 @@ class AutocompleteResults {
               ) {
                 columnSuggestions.push({
                   value: sqlUtils.backTickIfNeeded(
-                    self.dialect(),
+                    self.snippet.connector(),
                     column.identifierChain[column.identifierChain.length - 1].name
                   ),
                   filterValue: column.identifierChain[column.identifierChain.length - 1].name,
@@ -1154,7 +1156,7 @@ class AutocompleteResults {
               typeof column.type !== 'undefined' && column.type !== 'COLREF' ? column.type : 'T';
             if (column.alias) {
               columnSuggestions.push({
-                value: sqlUtils.backTickIfNeeded(self.dialect(), column.alias),
+                value: sqlUtils.backTickIfNeeded(self.snippet.connector(), column.alias),
                 filterValue: column.alias,
                 meta: type,
                 category: CATEGORIES.COLUMN,
@@ -1165,7 +1167,7 @@ class AutocompleteResults {
             } else if (column.identifierChain && column.identifierChain.length > 0) {
               columnSuggestions.push({
                 value: sqlUtils.backTickIfNeeded(
-                  self.dialect(),
+                  self.snippet.connector(),
                   column.identifierChain[column.identifierChain.length - 1].name
                 ),
                 filterValue: column.identifierChain[column.identifierChain.length - 1].name,
@@ -1199,7 +1201,10 @@ class AutocompleteResults {
                   .getChildren({ silenceErrors: true, cancellable: true })
                   .done(childEntries => {
                     childEntries.forEach(childEntry => {
-                      let name = sqlUtils.backTickIfNeeded(self.dialect(), childEntry.name);
+                      let name = sqlUtils.backTickIfNeeded(
+                        self.snippet.connector(),
+                        childEntry.name
+                      );
                       if (
                         self.dialect() === DIALECT.hive &&
                         (childEntry.isArray() || childEntry.isMap())
@@ -1300,9 +1305,7 @@ class AutocompleteResults {
   }
 
   static mergeColumns(columnSuggestions) {
-    columnSuggestions.sort((a, b) => {
-      return a.value.localeCompare(b.value);
-    });
+    columnSuggestions.sort((a, b) => a.value.localeCompare(b.value));
 
     for (let i = 0; i < columnSuggestions.length; i++) {
       const suggestion = columnSuggestions[i];

+ 12 - 10
desktop/core/src/desktop/js/sql/sqlUtils.js

@@ -781,31 +781,33 @@ export const resolveCatalogEntry = options => {
 
 export default {
   autocompleteFilter: autocompleteFilter,
-  backTickIfNeeded: (sourceType, identifier) => {
-    if (identifier.indexOf('`') === 0) {
+  backTickIfNeeded: (connector, identifier) => {
+    const quoteChar =
+      (connector.dialect_properties && connector.dialect_properties.sql_identifier_quote) || '`';
+    if (identifier.indexOf(quoteChar) === 0) {
       return identifier;
     }
     const upperIdentifier = identifier.toUpperCase();
     if (
-      sourceType === 'hive' &&
+      connector.dialect === 'hive' &&
       (hiveReservedKeywords[upperIdentifier] || extraHiveReservedKeywords[upperIdentifier])
     ) {
-      return '`' + identifier + '`';
+      return quoteChar + identifier + quoteChar;
     }
-    if (sourceType === 'impala' && impalaReservedKeywords[upperIdentifier]) {
-      return '`' + identifier + '`';
+    if (connector.dialect === 'impala' && impalaReservedKeywords[upperIdentifier]) {
+      return quoteChar + identifier + quoteChar;
     }
     if (
-      sourceType !== 'impala' &&
-      sourceType !== 'hive' &&
+      connector.dialect !== 'impala' &&
+      connector.dialect !== 'hive' &&
       (impalaReservedKeywords[upperIdentifier] ||
         hiveReservedKeywords[upperIdentifier] ||
         extraHiveReservedKeywords[upperIdentifier])
     ) {
-      return '`' + identifier + '`';
+      return quoteChar + identifier + quoteChar;
     }
     if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(identifier)) {
-      return '`' + identifier + '`';
+      return quoteChar + identifier + quoteChar;
     }
     return identifier;
   },

+ 3 - 3
desktop/libs/indexer/src/indexer/templates/importer.mako

@@ -1638,7 +1638,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
           var statementCols = [];
           var temporaryColumns = [];
           sampleCols.forEach(function (sampleCol) {
-            statementCols.push(sqlUtils.backTickIfNeeded(self.sourceType, sampleCol.name()));
+            statementCols.push(sqlUtils.backTickIfNeeded({ id: self.sourceType, dialect: self.sourceType }, sampleCol.name()));
             var col = {
               name: sampleCol.name(),
               type: sampleCol.type()
@@ -1658,12 +1658,12 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
 
           var statement = 'SELECT ';
           statement += statementCols.join(',\n    ');
-          statement += '\n FROM ' + sqlUtils.backTickIfNeeded(self.sourceType, tableName) + ';';
+          statement += '\n FROM ' + sqlUtils.backTickIfNeeded({ id: self.sourceType, dialect: self.sourceType }, tableName) + ';';
           if (!wizard.destination.fieldEditorValue() || wizard.destination.fieldEditorValue() === lastStatement) {
             wizard.destination.fieldEditorValue(statement);
           }
           lastStatement = statement;
-          wizard.destination.fieldEditorPlaceHolder('${ _('Example: SELECT') }' + ' * FROM ' + sqlUtils.backTickIfNeeded(self.sourceType, tableName));
+          wizard.destination.fieldEditorPlaceHolder('${ _('Example: SELECT') }' + ' * FROM ' + sqlUtils.backTickIfNeeded({ id: self.sourceType, dialect: self.sourceType }, tableName));
 
           var handle = dataCatalog.addTemporaryTable({
             namespace: self.namespace(),