|
|
@@ -117,6 +117,7 @@ var DataCatalog = (function () {
|
|
|
var self = this;
|
|
|
self.sourceType = sourceType;
|
|
|
self.entries = {};
|
|
|
+ self.temporaryEntries = {};
|
|
|
self.multiTableEntries = {};
|
|
|
self.store = localforage.createInstance({
|
|
|
name: 'HueDataCatalog_' + self.sourceType + '_' + STORAGE_POSTFIX
|
|
|
@@ -371,6 +372,135 @@ var DataCatalog = (function () {
|
|
|
return self.entries[generateEntryCacheId(options)];
|
|
|
};
|
|
|
|
|
|
+ /**
|
|
|
+ * Adds a temporary table to the data catalog. This would allow autocomplete etc. of tables that haven't
|
|
|
+ * been created yet.
|
|
|
+ *
|
|
|
+ * Calling this returns a handle that allows deletion of any created entries by calling delete() on the handle.
|
|
|
+ *
|
|
|
+ * @param {Object} options
|
|
|
+ * @param {string} options.name
|
|
|
+ * @param {ContextNamespace} options.namespace - The context namespace
|
|
|
+ * @param {ContextCompute} options.compute - The context compute
|
|
|
+ *
|
|
|
+ * @param {Object[]} options.columns
|
|
|
+ * @param {string} options.columns[].name
|
|
|
+ * @param {string} options.columns[].type
|
|
|
+ *
|
|
|
+ * @return {Object}
|
|
|
+ */
|
|
|
+ DataCatalog.prototype.addTemporaryTable = function (options) {
|
|
|
+ var self = this;
|
|
|
+ var tableDeferred = $.Deferred();
|
|
|
+ var path = ['default', options.name];
|
|
|
+
|
|
|
+ var identifiersToClean = [];
|
|
|
+
|
|
|
+ var databaseIdentifier = generateEntryCacheId({
|
|
|
+ namespace: options.namespace,
|
|
|
+ path: ['default']
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!self.temporaryEntries[databaseIdentifier]) {
|
|
|
+ var databaseDeferred = $.Deferred();
|
|
|
+ self.temporaryEntries[databaseIdentifier] = databaseDeferred.promise();
|
|
|
+ var databaseEntry = new DataCatalogEntry({
|
|
|
+ dataCatalog: self,
|
|
|
+ namespace: options.namespace,
|
|
|
+ compute: options.compute,
|
|
|
+ path: path,
|
|
|
+ definition: {
|
|
|
+ index: 0,
|
|
|
+ navOptLoaded: true,
|
|
|
+ type: 'database'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ identifiersToClean.push(databaseIdentifier);
|
|
|
+ databaseEntry.childrenPromise = $.Deferred().resolve([]).promise();
|
|
|
+ databaseDeferred.resolve(databaseEntry);
|
|
|
+ }
|
|
|
+
|
|
|
+ var removeTable = function () {}; // noop until actually added
|
|
|
+
|
|
|
+ self.temporaryEntries[databaseIdentifier].done(function (databaseEntry) {
|
|
|
+ databaseEntry.getChildren().done(function (existingTemporaryTables) {
|
|
|
+ var tableIdentifier = generateEntryCacheId({
|
|
|
+ namespace: options.namespace,
|
|
|
+ path: path
|
|
|
+ });
|
|
|
+ self.temporaryEntries[tableIdentifier] = tableDeferred.promise();
|
|
|
+ identifiersToClean.push(tableIdentifier);
|
|
|
+
|
|
|
+ var tableEntry = new DataCatalogEntry({
|
|
|
+ dataCatalog: self,
|
|
|
+ namespace: options.namespace,
|
|
|
+ compute: options.compute,
|
|
|
+ path: path,
|
|
|
+ definition: {
|
|
|
+ comment: '',
|
|
|
+ index: 0,
|
|
|
+ name: options.name,
|
|
|
+ navOptLoaded: true,
|
|
|
+ type: 'table'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ existingTemporaryTables.push(tableEntry);
|
|
|
+ var indexToDelete = existingTemporaryTables.length - 1;
|
|
|
+ removeTable = function () { existingTemporaryTables.splice(indexToDelete, 1); };
|
|
|
+
|
|
|
+ var childrenDeferred = $.Deferred();
|
|
|
+ tableEntry.childrenPromise = childrenDeferred.promise();
|
|
|
+
|
|
|
+ if (options.columns) {
|
|
|
+ var childEntries = [];
|
|
|
+ var index = 0;
|
|
|
+ options.columns.forEach(function (column) {
|
|
|
+ var columnPath = path.concat(column.name);
|
|
|
+ var columnIdentifier = generateEntryCacheId({
|
|
|
+ namespace: options.namespace,
|
|
|
+ path: columnPath
|
|
|
+ });
|
|
|
+
|
|
|
+ var columnDeferred = $.Deferred();
|
|
|
+ self.temporaryEntries[columnIdentifier] = columnDeferred.promise();
|
|
|
+ identifiersToClean.push(columnIdentifier);
|
|
|
+
|
|
|
+ var columnEntry = new DataCatalogEntry({
|
|
|
+ dataCatalog: self,
|
|
|
+ namespace: options.namespace,
|
|
|
+ compute: options.compute,
|
|
|
+ path: columnPath,
|
|
|
+ definition: {
|
|
|
+ comment: '',
|
|
|
+ index: index++,
|
|
|
+ name: column.name,
|
|
|
+ partitionKey: false,
|
|
|
+ type: column.type
|
|
|
+ }
|
|
|
+ });
|
|
|
+ columnDeferred.resolve(columnEntry);
|
|
|
+
|
|
|
+ childEntries.push(columnEntry)
|
|
|
+ });
|
|
|
+ childrenDeferred.resolve(childEntries);
|
|
|
+ } else {
|
|
|
+ childrenDeferred.resolve([]);
|
|
|
+ }
|
|
|
+
|
|
|
+ tableDeferred.resolve(tableEntry);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ delete: function () {
|
|
|
+ removeTable();
|
|
|
+ while (identifiersToClean.length) {
|
|
|
+ delete self.entries[identifiersToClean.pop()];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
/**
|
|
|
* @param {Object} options
|
|
|
* @param {string|string[]} options.path
|
|
|
@@ -378,11 +508,15 @@ var DataCatalog = (function () {
|
|
|
* @param {ContextCompute} options.compute - The context compute
|
|
|
* @param {Object} [options.definition] - The initial definition if not already set on the entry
|
|
|
* @param {boolean} [options.cachedOnly] - Default: false
|
|
|
+ * @param {boolean} [options.temporaryOnly] - Default: false
|
|
|
* @return {Promise}
|
|
|
*/
|
|
|
DataCatalog.prototype.getEntry = function (options) {
|
|
|
var self = this;
|
|
|
var identifier = generateEntryCacheId(options);
|
|
|
+ if (options.temporaryOnly) {
|
|
|
+ return self.temporaryEntries[identifier] || $.Deferred().reject().promise();
|
|
|
+ }
|
|
|
if (self.entries[identifier]) {
|
|
|
return self.entries[identifier];
|
|
|
}
|
|
|
@@ -696,7 +830,7 @@ var DataCatalog = (function () {
|
|
|
* @param {Object} options
|
|
|
* @param {string} [options.invalidate] - 'cache', 'invalidate' or 'invalidateAndFlush', default 'cache', only used for Impala
|
|
|
* @param {boolean} [options.cascade] - Default false, only used when the entry is for the source
|
|
|
- * @param {boolean [options.silenceErrors] - Default false
|
|
|
+ * @param {boolean} [options.silenceErrors] - Default false
|
|
|
* @return {CancellablePromise}
|
|
|
*/
|
|
|
DataCatalogEntry.prototype.clearCache = function (options) {
|
|
|
@@ -2177,6 +2311,29 @@ var DataCatalog = (function () {
|
|
|
|
|
|
return {
|
|
|
|
|
|
+ /**
|
|
|
+ * Adds a detached (temporary) entry to the data catalog. This would allow autocomplete etc. of tables that haven't
|
|
|
+ * been created yet.
|
|
|
+ *
|
|
|
+ * Calling this returns a handle that allows deletion of any created entries by calling delete() on the handle.
|
|
|
+ *
|
|
|
+ * @param {Object} options
|
|
|
+ * @param {string} options.sourceType
|
|
|
+ * @param {ContextNamespace} options.namespace - The context namespace
|
|
|
+ * @param {ContextCompute} options.compute - The context compute
|
|
|
+ * @param {string} options.name
|
|
|
+ *
|
|
|
+ * @param {Object[]} options.columns
|
|
|
+ * @param {string} options.columns[].name
|
|
|
+ * @param {string} options.columns[].type
|
|
|
+ * @param options
|
|
|
+ *
|
|
|
+ * @return {Object}
|
|
|
+ */
|
|
|
+ addTemporaryTable: function (options) {
|
|
|
+ return getCatalog(options.sourceType).addTemporaryTable(options);
|
|
|
+ },
|
|
|
+
|
|
|
/**
|
|
|
* @param {Object} options
|
|
|
* @param {string} options.sourceType
|
|
|
@@ -2184,6 +2341,7 @@ var DataCatalog = (function () {
|
|
|
* @param {ContextCompute} options.compute - The context compute
|
|
|
* @param {string|string[]} options.path
|
|
|
* @param {Object} [options.definition] - Optional initial definition
|
|
|
+ * @param {boolean} [options.temporaryOnly] - Default: false
|
|
|
*
|
|
|
* @return {Promise}
|
|
|
*/
|