diff --git a/RELEASE.md b/RELEASE.md
index a51b49280..c79b7c8a5 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -16,7 +16,7 @@ This document is a summary of code changes in Chaise. This is the vocabulary use
- [Changed] how we encode search filter in the url to use the new `search-box` sourcekey.
- [Added] `comment` support to display annotation.
- [Changed] `comment` behavior in annotations so that `false` is treated the same as empty string.
- - [Added] `elapsed_s` attribute to `Deriva-Client-Context` header object for all the http requests.
+ - [Added] `elapsed_ms` attribute to `Deriva-Client-Context` header object for all the http requests.
- [Added] `show_foreign_key_link` support.
- [Changed] `show_nulls` to `show_null` in display annotation.
diff --git a/docs/dev-docs/api.md b/docs/dev-docs/api.md
index cb844f089..6bd6c9719 100644
--- a/docs/dev-docs/api.md
+++ b/docs/dev-docs/api.md
@@ -92,7 +92,8 @@ to use for ERMrest JavaScript agents.
* [.Schema](#ERMrest.Schema)
* [new Schema(catalog, jsonSchema)](#new_ERMrest.Schema_new)
* [.catalog](#ERMrest.Schema+catalog) : [Catalog
](#ERMrest.Catalog)
- * [.name](#ERMrest.Schema+name)
+ * [.name](#ERMrest.Schema+name) : string
+ * [.RID](#ERMrest.Schema+RID) : string
* [.ignore](#ERMrest.Schema+ignore) : boolean
* [.annotations](#ERMrest.Schema+annotations) : [Annotations
](#ERMrest.Annotations)
* [.rights](#ERMrest.Schema+rights) : Object
@@ -109,7 +110,8 @@ to use for ERMrest JavaScript agents.
* [new Table(schema, jsonTable)](#new_ERMrest.Table_new)
* _instance_
* [.schema](#ERMrest.Table+schema) : [Schema
](#ERMrest.Schema)
- * [.name](#ERMrest.Table+name)
+ * [.name](#ERMrest.Table+name) : string
+ * [.RID](#ERMrest.Table+RID) : string
* [.entity](#ERMrest.Table+entity) : [Entity
](#ERMrest.Table.Entity)
* [.ignore](#ERMrest.Table+ignore) : boolean
* [._baseTable](#ERMrest.Table+_baseTable) : [Table
](#ERMrest.Table)
@@ -171,6 +173,7 @@ to use for ERMrest JavaScript agents.
* [.isSystemColumn](#ERMrest.Column+isSystemColumn) : Boolean
* [.isImmutable](#ERMrest.Column+isImmutable) : Boolean
* [.name](#ERMrest.Column+name) : string
+ * [.RID](#ERMrest.Column+RID) : string
* [.type](#ERMrest.Column+type) : [Type
](#ERMrest.Type)
* [.ignore](#ERMrest.Column+ignore) : boolean
* [.annotations](#ERMrest.Column+annotations) : [Annotations
](#ERMrest.Annotations)
@@ -210,6 +213,7 @@ to use for ERMrest JavaScript agents.
* [.colset](#ERMrest.Key+colset) : [ColSet
](#ERMrest.ColSet)
* [.annotations](#ERMrest.Key+annotations) : [Annotations
](#ERMrest.Annotations)
* [.comment](#ERMrest.Key+comment) : string
+ * [.RID](#ERMrest.Key+RID) : string
* [.constraint_names](#ERMrest.Key+constraint_names) : Array
* [.name](#ERMrest.Key+name) : string
* [.simple](#ERMrest.Key+simple) : boolean
@@ -236,6 +240,8 @@ to use for ERMrest JavaScript agents.
* [.get(colset)](#ERMrest.ForeignKeys+get) ⇒ [Array.<ForeignKeyRef>
](#ERMrest.ForeignKeyRef)
* [.ForeignKeyRef](#ERMrest.ForeignKeyRef)
* [new ForeignKeyRef(table, jsonFKR)](#new_ERMrest.ForeignKeyRef_new)
+ * [.table](#ERMrest.ForeignKeyRef+table) : [Table
](#ERMrest.Table)
+ * [.RID](#ERMrest.ForeignKeyRef+RID) : string
* [.colset](#ERMrest.ForeignKeyRef+colset) : [ColSet
](#ERMrest.ColSet)
* [.key](#ERMrest.ForeignKeyRef+key) : [Key
](#ERMrest.Key)
* [.rights](#ERMrest.ForeignKeyRef+rights) : Object
@@ -246,6 +252,7 @@ to use for ERMrest JavaScript agents.
* [.ignore](#ERMrest.ForeignKeyRef+ignore) : boolean
* [.annotations](#ERMrest.ForeignKeyRef+annotations) : [Annotations
](#ERMrest.Annotations)
* [.comment](#ERMrest.ForeignKeyRef+comment) : string
+ * [.compressedDataSource](#ERMrest.ForeignKeyRef+compressedDataSource)
* [.name](#ERMrest.ForeignKeyRef+name) : string
* [.simple](#ERMrest.ForeignKeyRef+simple) : Boolean
* [.toString(reverse, isLeft)](#ERMrest.ForeignKeyRef+toString) ⇒ string
@@ -332,6 +339,7 @@ to use for ERMrest JavaScript agents.
* [.appLink](#ERMrest.Reference+appLink) : String
* [.csvDownloadLink](#ERMrest.Reference+csvDownloadLink) ⇒ String
* [.defaultLogInfo](#ERMrest.Reference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.Reference+filterLogInfo) : Object
* [.defaultExportTemplate](#ERMrest.Reference+defaultExportTemplate) : string
* [.removeAllFacetFilters(sameFilter, sameCustomFacet, sameFacet)](#ERMrest.Reference+removeAllFacetFilters) ⇒ ERMrest.reference
* [.hideFacets()](#ERMrest.Reference+hideFacets) ⇒ [Reference
](#ERMrest.Reference)
@@ -389,7 +397,7 @@ to use for ERMrest JavaScript agents.
* [.isPseudo](#ERMrest.ReferenceColumn+isPseudo) : boolean
* [.table](#ERMrest.ReferenceColumn+table) : [Table
](#ERMrest.Table)
* [.name](#ERMrest.ReferenceColumn+name) : string
- * [.dataSource](#ERMrest.ReferenceColumn+dataSource)
+ * [.compressedDataSource](#ERMrest.ReferenceColumn+compressedDataSource)
* [.displayname](#ERMrest.ReferenceColumn+displayname) : object
* [.type](#ERMrest.ReferenceColumn+type) : [Type
](#ERMrest.Type)
* [.nullok](#ERMrest.ReferenceColumn+nullok) : Boolean
@@ -463,6 +471,7 @@ to use for ERMrest JavaScript agents.
* [.reference](#ERMrest.FacetColumn+reference) : [Reference
](#ERMrest.Reference)
* [.index](#ERMrest.FacetColumn+index) : int
* [.dataSource](#ERMrest.FacetColumn+dataSource) : obj
\| string
+ * [.compressedDataSource](#ERMrest.FacetColumn+compressedDataSource) : obj
\| string
* [.filters](#ERMrest.FacetColumn+filters)
* [.isOpen](#ERMrest.FacetColumn+isOpen) : Boolean
* [.hasPath](#ERMrest.FacetColumn+hasPath) : Boolean
@@ -535,6 +544,7 @@ to use for ERMrest JavaScript agents.
* [.unfilteredReference](#ERMrest.AttributeGroupReference+unfilteredReference) : [Reference
](#ERMrest.Reference)
* [.ermrestPath](#ERMrest.AttributeGroupReference+ermrestPath) : string
* [.defaultLogInfo](#ERMrest.AttributeGroupReference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.AttributeGroupReference+filterLogInfo) : Object
* [.read([limit], contextHeaderParams)](#ERMrest.AttributeGroupReference+read) ⇒ ERMRest.AttributeGroupPage
* [.getColumnByName(name)](#ERMrest.AttributeGroupReference+getColumnByName) ⇒ ERMrest.AttributeGroupColumn
* [.AttributeGroupPage](#ERMrest.AttributeGroupPage)
@@ -640,6 +650,7 @@ to use for ERMrest JavaScript agents.
* [.appLink](#ERMrest.Reference+appLink) : String
* [.csvDownloadLink](#ERMrest.Reference+csvDownloadLink) ⇒ String
* [.defaultLogInfo](#ERMrest.Reference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.Reference+filterLogInfo) : Object
* [.defaultExportTemplate](#ERMrest.Reference+defaultExportTemplate) : string
* [.removeAllFacetFilters(sameFilter, sameCustomFacet, sameFacet)](#ERMrest.Reference+removeAllFacetFilters) ⇒ ERMrest.reference
* [.hideFacets()](#ERMrest.Reference+hideFacets) ⇒ [Reference
](#ERMrest.Reference)
@@ -672,6 +683,7 @@ to use for ERMrest JavaScript agents.
* [.unfilteredReference](#ERMrest.AttributeGroupReference+unfilteredReference) : [Reference
](#ERMrest.Reference)
* [.ermrestPath](#ERMrest.AttributeGroupReference+ermrestPath) : string
* [.defaultLogInfo](#ERMrest.AttributeGroupReference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.AttributeGroupReference+filterLogInfo) : Object
* [.read([limit], contextHeaderParams)](#ERMrest.AttributeGroupReference+read) ⇒ ERMRest.AttributeGroupPage
* [.getColumnByName(name)](#ERMrest.AttributeGroupReference+getColumnByName) ⇒ ERMrest.AttributeGroupColumn
* [.AttributeGroupPage](#ERMrest.AttributeGroupPage) : object
@@ -692,6 +704,7 @@ to use for ERMrest JavaScript agents.
* [.getServer(uri, [contextHeaderParams])](#ERMrest.getServer) ⇒ [Server
](#ERMrest.Server)
* [.parse(uri, catalogObject)](#ERMrest.parse) ⇒ ERMrest.Location
* [.resolve(uri, [contextHeaderParams])](#ERMrest.resolve) ⇒ Promise
+ * [.getElapsedTime()](#ERMrest.getElapsedTime) ⇒ integer
@@ -971,7 +984,8 @@ it will throw an error
* [.Schema](#ERMrest.Schema)
* [new Schema(catalog, jsonSchema)](#new_ERMrest.Schema_new)
* [.catalog](#ERMrest.Schema+catalog) : [Catalog
](#ERMrest.Catalog)
- * [.name](#ERMrest.Schema+name)
+ * [.name](#ERMrest.Schema+name) : string
+ * [.RID](#ERMrest.Schema+RID) : string
* [.ignore](#ERMrest.Schema+ignore) : boolean
* [.annotations](#ERMrest.Schema+annotations) : [Annotations
](#ERMrest.Annotations)
* [.rights](#ERMrest.Schema+rights) : Object
@@ -996,7 +1010,15 @@ Constructor for the Catalog.
**Kind**: instance property of [Schema
](#ERMrest.Schema)
-#### schema.name
+#### schema.name : string
+the database name of the schema
+
+**Kind**: instance property of [Schema
](#ERMrest.Schema)
+
+
+#### schema.RID : string
+The RID of this schema (might not be defined)
+
**Kind**: instance property of [Schema
](#ERMrest.Schema)
@@ -1085,7 +1107,8 @@ get table by table name
* [new Table(schema, jsonTable)](#new_ERMrest.Table_new)
* _instance_
* [.schema](#ERMrest.Table+schema) : [Schema
](#ERMrest.Schema)
- * [.name](#ERMrest.Table+name)
+ * [.name](#ERMrest.Table+name) : string
+ * [.RID](#ERMrest.Table+RID) : string
* [.entity](#ERMrest.Table+entity) : [Entity
](#ERMrest.Table.Entity)
* [.ignore](#ERMrest.Table+ignore) : boolean
* [._baseTable](#ERMrest.Table+_baseTable) : [Table
](#ERMrest.Table)
@@ -1135,7 +1158,15 @@ Constructor for Table.
**Kind**: instance property of [Table
](#ERMrest.Table)
-#### table.name
+#### table.name : string
+the database name of the table
+
+**Kind**: instance property of [Table
](#ERMrest.Table)
+
+
+#### table.RID : string
+The RID of this table (might not be defined)
+
**Kind**: instance property of [Table
](#ERMrest.Table)
@@ -1599,6 +1630,7 @@ Constructor for Columns.
* [.isSystemColumn](#ERMrest.Column+isSystemColumn) : Boolean
* [.isImmutable](#ERMrest.Column+isImmutable) : Boolean
* [.name](#ERMrest.Column+name) : string
+ * [.RID](#ERMrest.Column+RID) : string
* [.type](#ERMrest.Column+type) : [Type
](#ERMrest.Type)
* [.ignore](#ERMrest.Column+ignore) : boolean
* [.annotations](#ERMrest.Column+annotations) : [Annotations
](#ERMrest.Annotations)
@@ -1675,6 +1707,14 @@ Mentions whether this column is immutable depending on update rights
#### column.name : string
+The database name of this column
+
+**Kind**: instance property of [Column
](#ERMrest.Column)
+
+
+#### column.RID : string
+The RID of this column (might not be defined)
+
**Kind**: instance property of [Column
](#ERMrest.Column)
@@ -1958,6 +1998,7 @@ get the key by the column set
* [.colset](#ERMrest.Key+colset) : [ColSet
](#ERMrest.ColSet)
* [.annotations](#ERMrest.Key+annotations) : [Annotations
](#ERMrest.Annotations)
* [.comment](#ERMrest.Key+comment) : string
+ * [.RID](#ERMrest.Key+RID) : string
* [.constraint_names](#ERMrest.Key+constraint_names) : Array
* [.name](#ERMrest.Key+name) : string
* [.simple](#ERMrest.Key+simple) : boolean
@@ -1993,6 +2034,12 @@ Reference to the table that this Key belongs to.
#### key.comment : string
Documentation for this key
+**Kind**: instance property of [Key
](#ERMrest.Key)
+
+
+#### key.RID : string
+The RID of this key (might not be defined)
+
**Kind**: instance property of [Key
](#ERMrest.Key)
@@ -2203,6 +2250,8 @@ get the foreign key of the given column set
* [.ForeignKeyRef](#ERMrest.ForeignKeyRef)
* [new ForeignKeyRef(table, jsonFKR)](#new_ERMrest.ForeignKeyRef_new)
+ * [.table](#ERMrest.ForeignKeyRef+table) : [Table
](#ERMrest.Table)
+ * [.RID](#ERMrest.ForeignKeyRef+RID) : string
* [.colset](#ERMrest.ForeignKeyRef+colset) : [ColSet
](#ERMrest.ColSet)
* [.key](#ERMrest.ForeignKeyRef+key) : [Key
](#ERMrest.Key)
* [.rights](#ERMrest.ForeignKeyRef+rights) : Object
@@ -2213,6 +2262,7 @@ get the foreign key of the given column set
* [.ignore](#ERMrest.ForeignKeyRef+ignore) : boolean
* [.annotations](#ERMrest.ForeignKeyRef+annotations) : [Annotations
](#ERMrest.Annotations)
* [.comment](#ERMrest.ForeignKeyRef+comment) : string
+ * [.compressedDataSource](#ERMrest.ForeignKeyRef+compressedDataSource)
* [.name](#ERMrest.ForeignKeyRef+name) : string
* [.simple](#ERMrest.ForeignKeyRef+simple) : Boolean
* [.toString(reverse, isLeft)](#ERMrest.ForeignKeyRef+toString) ⇒ string
@@ -2227,6 +2277,18 @@ get the foreign key of the given column set
| table | [Table
](#ERMrest.Table) |
| jsonFKR | Object
|
+
+
+#### foreignKeyRef.table : [Table
](#ERMrest.Table)
+The table that this foreignkey is defined on (from table)
+
+**Kind**: instance property of [ForeignKeyRef
](#ERMrest.ForeignKeyRef)
+
+
+#### foreignKeyRef.RID : string
+The RID of this column (might not be defined)
+
+**Kind**: instance property of [ForeignKeyRef
](#ERMrest.ForeignKeyRef)
#### foreignKeyRef.colset : [ColSet
](#ERMrest.ColSet)
@@ -2275,10 +2337,17 @@ The constraint names for this foreign key
Documentation for this foreign key reference
**Kind**: instance property of [ForeignKeyRef
](#ERMrest.ForeignKeyRef)
+
+
+#### foreignKeyRef.compressedDataSource
+the compressed source path from the main reference to this column
+
+**Kind**: instance property of [ForeignKeyRef
](#ERMrest.ForeignKeyRef)
+**Type{object}**:
#### foreignKeyRef.name : string
-A unique nam that can be used for referring to this foreignkey.
+A unique name that can be used for referring to this foreignkey.
**Kind**: instance property of [ForeignKeyRef
](#ERMrest.ForeignKeyRef)
@@ -2754,6 +2823,7 @@ Constructor for a ParsedFilter.
* [.appLink](#ERMrest.Reference+appLink) : String
* [.csvDownloadLink](#ERMrest.Reference+csvDownloadLink) ⇒ String
* [.defaultLogInfo](#ERMrest.Reference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.Reference+filterLogInfo) : Object
* [.defaultExportTemplate](#ERMrest.Reference+defaultExportTemplate) : string
* [.removeAllFacetFilters(sameFilter, sameCustomFacet, sameFacet)](#ERMrest.Reference+removeAllFacetFilters) ⇒ ERMrest.reference
* [.hideFacets()](#ERMrest.Reference+hideFacets) ⇒ [Reference
](#ERMrest.Reference)
@@ -3063,7 +3133,24 @@ NOTE It will not have the same sort and paging as the reference.
#### reference.defaultLogInfo : Object
The default information that we want to be logged. This includes:
- - catalog, schema_table, cfacet, cfacet_str, cfacet_path, facets
+ - catalog, schema_table
+TODO Evaluate whether we even need this function
+
+**Kind**: instance property of [Reference
](#ERMrest.Reference)
+
+
+#### reference.filterLogInfo : Object
+The object that can be logged to capture the filter state of the reference.
+The return object can have:
+ - filters: the facet object.
+ - custom_filters:
+ - the filter strings that parser couldn't turn to facet.
+ - if we could turn the custom filter to facet, this will return `true`
+ - cfacet: if there's a cfacet it will be 1
+ - cfacet_str: if cfacet=1, it will be displayname of cfacet.
+ - cfacet_path: if cfacet=1, it will be ermrest path of cfacet.
+This function creates a new object everytime that it's called, so it
+can be manipulated further.
**Kind**: instance property of [Reference
](#ERMrest.Reference)
@@ -3857,7 +3944,7 @@ count aggregate representation
* [.isPseudo](#ERMrest.ReferenceColumn+isPseudo) : boolean
* [.table](#ERMrest.ReferenceColumn+table) : [Table
](#ERMrest.Table)
* [.name](#ERMrest.ReferenceColumn+name) : string
- * [.dataSource](#ERMrest.ReferenceColumn+dataSource)
+ * [.compressedDataSource](#ERMrest.ReferenceColumn+compressedDataSource)
* [.displayname](#ERMrest.ReferenceColumn+displayname) : object
* [.type](#ERMrest.ReferenceColumn+type) : [Type
](#ERMrest.Type)
* [.nullok](#ERMrest.ReferenceColumn+nullok) : Boolean
@@ -3905,10 +3992,10 @@ indicates that this object represents a Column.
name of the column.
**Kind**: instance property of [ReferenceColumn
](#ERMrest.ReferenceColumn)
-
+
-#### referenceColumn.dataSource
-the source path from the main reference to this column
+#### referenceColumn.compressedDataSource
+the compressed source path from the main reference to this column
**Kind**: instance property of [ReferenceColumn
](#ERMrest.ReferenceColumn)
**Type{object}**:
@@ -4610,6 +4697,7 @@ Indicates that this ReferenceColumn is an inbound foreign key.
* [.reference](#ERMrest.FacetColumn+reference) : [Reference
](#ERMrest.Reference)
* [.index](#ERMrest.FacetColumn+index) : int
* [.dataSource](#ERMrest.FacetColumn+dataSource) : obj
\| string
+ * [.compressedDataSource](#ERMrest.FacetColumn+compressedDataSource) : obj
\| string
* [.filters](#ERMrest.FacetColumn+filters)
* [.isOpen](#ERMrest.FacetColumn+isOpen) : Boolean
* [.hasPath](#ERMrest.FacetColumn+hasPath) : Boolean
@@ -4693,6 +4781,12 @@ NOTE: Might not be needed
A valid data-source path
NOTE: we're not validating this data-source, we assume that this is valid.
+**Kind**: instance property of [FacetColumn
](#ERMrest.FacetColumn)
+
+
+#### facetColumn.compressedDataSource : obj
\| string
+the compressed version of data source data-source path
+
**Kind**: instance property of [FacetColumn
](#ERMrest.FacetColumn)
@@ -5342,6 +5436,7 @@ parent table (not the end table).
* [.unfilteredReference](#ERMrest.AttributeGroupReference+unfilteredReference) : [Reference
](#ERMrest.Reference)
* [.ermrestPath](#ERMrest.AttributeGroupReference+ermrestPath) : string
* [.defaultLogInfo](#ERMrest.AttributeGroupReference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.AttributeGroupReference+filterLogInfo) : Object
* [.read([limit], contextHeaderParams)](#ERMrest.AttributeGroupReference+read) ⇒ ERMRest.AttributeGroupPage
* [.getColumnByName(name)](#ERMrest.AttributeGroupReference+getColumnByName) ⇒ ERMrest.AttributeGroupColumn
@@ -5441,6 +5536,13 @@ NOTE:
#### attributeGroupReference.defaultLogInfo : Object
The default information that we want to be logged including catalog, schema_table, and facet (filter).
+**Kind**: instance property of [AttributeGroupReference
](#ERMrest.AttributeGroupReference)
+
+
+#### attributeGroupReference.filterLogInfo : Object
+The filter information that should be logged
+Currently only includes the search term.
+
**Kind**: instance property of [AttributeGroupReference
](#ERMrest.AttributeGroupReference)
@@ -6269,6 +6371,7 @@ get PathColumn object by column name
* [.appLink](#ERMrest.Reference+appLink) : String
* [.csvDownloadLink](#ERMrest.Reference+csvDownloadLink) ⇒ String
* [.defaultLogInfo](#ERMrest.Reference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.Reference+filterLogInfo) : Object
* [.defaultExportTemplate](#ERMrest.Reference+defaultExportTemplate) : string
* [.removeAllFacetFilters(sameFilter, sameCustomFacet, sameFacet)](#ERMrest.Reference+removeAllFacetFilters) ⇒ ERMrest.reference
* [.hideFacets()](#ERMrest.Reference+hideFacets) ⇒ [Reference
](#ERMrest.Reference)
@@ -6578,7 +6681,24 @@ NOTE It will not have the same sort and paging as the reference.
#### reference.defaultLogInfo : Object
The default information that we want to be logged. This includes:
- - catalog, schema_table, cfacet, cfacet_str, cfacet_path, facets
+ - catalog, schema_table
+TODO Evaluate whether we even need this function
+
+**Kind**: instance property of [Reference
](#ERMrest.Reference)
+
+
+#### reference.filterLogInfo : Object
+The object that can be logged to capture the filter state of the reference.
+The return object can have:
+ - filters: the facet object.
+ - custom_filters:
+ - the filter strings that parser couldn't turn to facet.
+ - if we could turn the custom filter to facet, this will return `true`
+ - cfacet: if there's a cfacet it will be 1
+ - cfacet_str: if cfacet=1, it will be displayname of cfacet.
+ - cfacet_path: if cfacet=1, it will be ermrest path of cfacet.
+This function creates a new object everytime that it's called, so it
+can be manipulated further.
**Kind**: instance property of [Reference
](#ERMrest.Reference)
@@ -6973,6 +7093,7 @@ Check the sort object. Does not change the `this._location` object.
* [.unfilteredReference](#ERMrest.AttributeGroupReference+unfilteredReference) : [Reference
](#ERMrest.Reference)
* [.ermrestPath](#ERMrest.AttributeGroupReference+ermrestPath) : string
* [.defaultLogInfo](#ERMrest.AttributeGroupReference+defaultLogInfo) : Object
+ * [.filterLogInfo](#ERMrest.AttributeGroupReference+filterLogInfo) : Object
* [.read([limit], contextHeaderParams)](#ERMrest.AttributeGroupReference+read) ⇒ ERMRest.AttributeGroupPage
* [.getColumnByName(name)](#ERMrest.AttributeGroupReference+getColumnByName) ⇒ ERMrest.AttributeGroupColumn
@@ -7072,6 +7193,13 @@ NOTE:
#### attributeGroupReference.defaultLogInfo : Object
The default information that we want to be logged including catalog, schema_table, and facet (filter).
+**Kind**: instance property of [AttributeGroupReference
](#ERMrest.AttributeGroupReference)
+
+
+#### attributeGroupReference.filterLogInfo : Object
+The filter information that should be logged
+Currently only includes the search term.
+
**Kind**: instance property of [AttributeGroupReference
](#ERMrest.AttributeGroupReference)
@@ -7347,6 +7475,12 @@ ERMrest.resolve('https://example.org/catalog/42/entity/s:t/k=123').then(
| uri | string
| An ERMrest resource URI, such as `https://example.org/ermrest/catalog/1/entity/s:t/k=123`. |
| [contextHeaderParams] | Object
| An optional context header parameters object. The (key, value) pairs from the object are converted to URL `key=value` query parameters and appended to every request to the ERMrest service. |
+
+
+### ERMrest.getElapsedTime() ⇒ integer
+**Kind**: static method of [ERMrest
](#ERMrest)
+**Returns**: integer
- A value set to determine the elapsed time
+since the ermrestJS has been available (milliseconds).
## formatDate() ⇒
diff --git a/js/ag_reference.js b/js/ag_reference.js
index 747799c3e..62d8e4122 100644
--- a/js/ag_reference.js
+++ b/js/ag_reference.js
@@ -350,9 +350,11 @@ AttributeGroupReference.prototype = {
uri += "?limit=" + (limit+1);
}
- var currRef = this;
+ var currRef = this, action = "read";
if (!contextHeaderParams || !isObject(contextHeaderParams)) {
- contextHeaderParams = {"action": "read"};
+ contextHeaderParams = {"action": action};
+ } else if (typeof contextHeaderParams.action === "string") {
+ action = contextHeaderParams.action;
}
var config = {
headers: this._generateContextHeader(contextHeaderParams, limit)
@@ -395,7 +397,10 @@ AttributeGroupReference.prototype = {
// a new location without paging
var newLocation = currRef.location.changePage();
var referenceWithoutPaging = new AttributeGroupReference(currRef._keyColumns, currRef._aggregateColumns, newLocation, currRef._catalog, currRef.table, currRef._context);
- referenceWithoutPaging.read(limit).then(function rereadReference(rereadPage) {
+
+ // remove the function and replace it with auto-reload
+ contextHeaderParams.action = action.substring(0,action.lastIndexOf(";")+1) + "auto-reload";
+ referenceWithoutPaging.read(limit, contextHeaderParams).then(function rereadReference(rereadPage) {
defer.resolve(rereadPage);
}, function error(err) {
throw err;
@@ -533,6 +538,19 @@ AttributeGroupReference.prototype = {
return obj;
},
+ /**
+ * The filter information that should be logged
+ * Currently only includes the search term.
+ * @type {Object}
+ */
+ get filterLogInfo() {
+ var obj = {};
+ if (isObjectAndNotNull(this.location.searchObject) && typeof this.location.searchTerm === "string" && this.location.searchTerm) {
+ obj.filters = _compressFacetObject({"and": [{"source": "search-box", "search": [this.location.searchTerm]}]});
+ }
+ return obj;
+ },
+
_generateContextHeader: function (contextHeaderParams, page_size) {
if (!contextHeaderParams || !isObject(contextHeaderParams)) {
contextHeaderParams = {};
diff --git a/js/column.js b/js/column.js
index acbe325e9..6005e3e9f 100644
--- a/js/column.js
+++ b/js/column.js
@@ -150,20 +150,23 @@ ReferenceColumn.prototype = {
},
/**
- * the source path from the main reference to this column
+ * the compressed source path from the main reference to this column
* @type{Object}
*/
- get dataSource() {
- if (this._dataSource === undefined) {
+ get compressedDataSource() {
+ if (this._compressedDataSource === undefined) {
+ var ds;
if (this.sourceObject && this.sourceObject.source) {
- this._dataSource = this.sourceObject.source;
+ ds = this.sourceObject.source;
} else if (this._simple) {
- this._dataSource = this._baseCols[0].name;
+ ds = this._baseCols[0].name;
} else {
- this._dataSource = null;
+ ds = null;
}
+
+ this._compressedDataSource = _compressSource(ds);
}
- return this._dataSource;
+ return this._compressedDataSource;
},
/**
@@ -1455,6 +1458,14 @@ Object.defineProperty(PseudoColumn.prototype, "hasAggregate", {
return this._hasAggregate;
}
});
+Object.defineProperty(PseudoColumn.prototype, "aggregateFn", {
+ get: function () {
+ if (this._aggregateFn === undefined) {
+ this._aggregateFn = this.hasAggregate ? this.sourceObject.aggregate : null;
+ }
+ return this._aggregateFn;
+ }
+});
/**
* Returns a reference to the current pseudo-column
@@ -1541,7 +1552,7 @@ Object.defineProperty(PseudoColumn.prototype, "reference", {
// make sure data-source is available on the reference
// TODO this has been added to be consistent with the old related reference apis
// other apis are not available, maybe we should add them as well? (origFKR, etc.)
- self._reference.dataSource = self.dataSource;
+ self._reference.compressedDataSource = self.compressedDataSource;
// make sure the refernece has the correct displayname
if (self.hasPath) {
@@ -1960,21 +1971,23 @@ Object.defineProperty(ForeignKeyPseudoColumn.prototype, "display", {
return this._display_cached;
}
});
-Object.defineProperty(ForeignKeyPseudoColumn.prototype, "dataSource", {
+Object.defineProperty(ForeignKeyPseudoColumn.prototype, "compressedDataSource", {
get: function () {
- if (this._dataSource === undefined) {
+ if (this._compressedDataSource === undefined) {
+ var ds;
if (this.sourceObject && this.sourceObject.source) {
- this._dataSource = this.sourceObject.source;
+ ds = this.sourceObject.source;
} else if (this.table.shortestKey.length === 1){
- this._dataSource = [
+ ds = [
{"outbound": this.foreignKey.constraint_names[0]},
this.table.shortestKey[0].name
];
} else {
- this._dataSource = null;
+ ds = null;
}
+ this._compressedDataSource = _compressSource(ds);
}
- return this._dataSource;
+ return this._compressedDataSource;
}
});
@@ -2635,18 +2648,18 @@ Object.defineProperty(InboundForeignKeyPseudoColumn.prototype, "nullok", {
throw new Error("can not use this type of column in entry mode.");
}
});
-Object.defineProperty(InboundForeignKeyPseudoColumn.prototype, "dataSource", {
+Object.defineProperty(InboundForeignKeyPseudoColumn.prototype, "compressedDataSource", {
get: function () {
- if (this._dataSource === undefined) {
+ if (this._compressedDataSource === undefined) {
+ var ds = null;
if (this.sourceObject && this.sourceObject.source) {
- this._dataSource = this.sourceObject.source;
- } else if (this.reference.dataSource){
- this._dataSource = this.reference.dataSource;
- } else {
- this._dataSource = null;
+ ds = _compressSource(this.sourceObject.source);
+ } else if (this.reference.compressedDataSource){
+ ds = this.reference.compressedDataSource;
}
+ this._compressedDataSource = ds;
}
- return this._dataSource;
+ return this._compressedDataSource;
}
});
@@ -2696,6 +2709,12 @@ function FacetColumn (reference, index, column, facetObject, filters) {
*/
this.dataSource = facetObject.source;
+ /**
+ * the compressed version of data source data-source path
+ * @type {obj|string}
+ */
+ this.compressedDataSource = _compressSource(facetObject.source);
+
/**
* Filters that are applied to this facet.
* @type{FacetFilter[]}
@@ -3327,8 +3346,21 @@ FacetColumn.prototype = {
* @return {Promise} A promise resolved with list of objects that have `uniqueId`, and `displayname`.
*/
getChoiceDisplaynames: function (contextHeaderParams) {
- var defer = module._q.defer();
- var filters = [];
+ var defer = module._q.defer(), filters = [];
+ var table = this._column.table, columnName = this._column.name;
+
+ var createRef = function (filterStrs) {
+ var uri = [
+ table.schema.catalog.server.uri ,"catalog" ,
+ table.schema.catalog.id, "entity",
+ module._fixedEncodeURIComponent(table.schema.name) + ":" + module._fixedEncodeURIComponent(table.name),
+ filterStrs.join(";")
+ ].join("/");
+
+ var ref = new Reference(module.parse(uri), table.schema.catalog).contextualize.compactSelect;
+ ref = ref.sort([{"column": columnName, "descending": false}]);
+ return ref;
+ };
// if no filter, just resolve with empty list.
if (this.choiceFilters.length === 0) {
@@ -3347,8 +3379,6 @@ FacetColumn.prototype = {
}
// otherwise generate an ermrest request to get the displaynames.
else {
-
- var table = this._column.table, columnName = this._column.name;
var filterStr = [];
// list of filters that we want their displaynames.
@@ -3369,18 +3399,7 @@ FacetColumn.prototype = {
}
// create a url
- var uri = [
- table.schema.catalog.server.uri ,"catalog" ,
- table.schema.catalog.id, "entity",
- module._fixedEncodeURIComponent(table.schema.name) + ":" + module._fixedEncodeURIComponent(table.name),
- filterStr.join(";")
- ].join("/");
-
- var ref = new Reference(module.parse(uri), table.schema.catalog).contextualize.compactSelect;
-
- ref = ref.sort([{"column": columnName, "descending": false}]);
-
- ref.read(this.choiceFilters.length, contextHeaderParams, true).then(function (page) {
+ createRef(filterStr).read(this.choiceFilters.length, contextHeaderParams, true).then(function (page) {
// create the response
page.tuples.forEach(function (t) {
filters.push({uniqueId: t.data[columnName], displayname: t.displayname, tuple: t});
diff --git a/js/core.js b/js/core.js
index 9971099c0..01fa0d2d4 100644
--- a/js/core.js
+++ b/js/core.js
@@ -325,7 +325,7 @@
headers[module.contextHeaderName] = contextHeaderParams;
} else {
headers[module.contextHeaderName] = {
- action: "model/snaptime",
+ action: ":,catalog/snaptime;load",
catalog: self.id
};
}
@@ -357,7 +357,7 @@
self.snaptime = snaptime;
var headers = {};
headers[module.contextHeaderName] = {
- action: "model/schema",
+ action: ":,catalog/schema;load",
catalog: self.id
};
return self.server.http.get(self._uri + "/schema", {headers: headers});
@@ -594,10 +594,17 @@
this.catalog = catalog;
/**
- *
+ * @desc the database name of the schema
+ * @type {string}
*/
this.name = jsonSchema.schema_name;
+ /**
+ * @desc The RID of this schema (might not be defined)
+ * @type {?string}
+ */
+ this.RID = jsonSchema.RID;
+
//this._uri = catalog._uri + "/schema/" + module._fixedEncodeURIComponent(this.name);
/**
@@ -807,11 +814,18 @@
this.schema = schema;
/**
- *
+ * @desc the database name of the table
+ * @type {string}
*/
this.name = jsonTable.table_name;
this._jsonTable = jsonTable;
+ /**
+ * @desc The RID of this table (might not be defined)
+ * @type {?string}
+ */
+ this.RID = jsonTable.RID;
+
this._nullValue = {}; // used to avoid recomputation of null value for different contexts.
@@ -2458,10 +2472,17 @@
this.isImmutable = this.rights.update === false;
/**
+ * The database name of this column
* @type {string}
*/
this.name = jsonColumn.name;
+ /**
+ * @desc The RID of this column (might not be defined)
+ * @type {?string}
+ */
+ this.RID = jsonColumn.RID;
+
/**
*
* @type {ERMrest.Type}
@@ -3048,6 +3069,12 @@
}
}
+ /**
+ * @desc The RID of this key (might not be defined)
+ * @type {?string}
+ */
+ this.RID = jsonKey.RID;
+
/**
* The exact `names` array in key definition
* @type {Array}
@@ -3558,8 +3585,18 @@
*/
this._table = table;
+ /**
+ * @desc The table that this foreignkey is defined on (from table)
+ * @type {ERMrest.Table}
+ */
this.table = table;
+ /**
+ * @desc The RID of this column (might not be defined)
+ * @type {?string}
+ */
+ this.RID = jsonFKR.RID;
+
var catalog = table.schema.catalog;
// create ColSet for foreign key columns
@@ -3678,7 +3715,25 @@
constructor: ForeignKeyRef,
/**
- * A unique nam that can be used for referring to this foreignkey.
+ * the compressed source path from the main reference to this column
+ * @type{Object}
+ */
+ get compressedDataSource() {
+ if (this._compressedDataSource === undefined) {
+ var ds = null;
+ if (this.table.shortestKey.length === 1) {
+ ds = [
+ {"outbound": this.constraint_names[0]},
+ this.table.shortestKey[0].name
+ ];
+ }
+ this._compressedDataSource = _compressSource(ds);
+ }
+ return this._compressedDataSource;
+ },
+
+ /**
+ * A unique name that can be used for referring to this foreignkey.
* @type {string}
*/
get name () {
diff --git a/js/export.js b/js/export.js
index ab587f656..bafa31d87 100644
--- a/js/export.js
+++ b/js/export.js
@@ -251,11 +251,6 @@ var ERMrest = (function(module) {
if (key in contextHeaderParams) continue;
contextHeaderParams[key] = self.reference.defaultLogInfo[key];
}
- // add the displayname and type of template
- contextHeaderParams.template = {
- displayname: self.template.displayname,
- type: self.template.type
- };
headers[module.contextHeaderName] = contextHeaderParams;
self.canceled = false;
diff --git a/js/http.js b/js/http.js
index 0eaa670bf..ee4199c5d 100644
--- a/js/http.js
+++ b/js/http.js
@@ -126,7 +126,6 @@
function wrap(method, fn, scope) {
scope = scope || window;
var cfg_idx = _method_to_config_idx[method];
- var startTime = Date.now();
return function() {
var args;
@@ -171,7 +170,7 @@
*
**/
if (typeof config.headers[module.contextHeaderName] === 'object') {
- config.headers[module.contextHeaderName].elapsed_s = Date.now() - startTime;
+ config.headers[module.contextHeaderName].elapsed_ms = module.getElapsedTime();
// encode and make sure it's not very lengthy
config.headers[module.contextHeaderName] = module._certifyContextHeader(config.headers[module.contextHeaderName]);
}
diff --git a/js/reference.js b/js/reference.js
index 8a67ed589..2fbb2f9d1 100644
--- a/js/reference.js
+++ b/js/reference.js
@@ -1156,8 +1156,12 @@
uri += (i === 0 ? "?defaults=" : ',') + module._fixedEncodeURIComponent(defaults[i]);
}
+ if (isObject(contextHeaderParams) && Array.isArray(contextHeaderParams.stack)) {
+ var stack = contextHeaderParams.stack;
+ stack[stack.length-1].num_created = data.length;
+ }
// create the context header params for log
- if (!contextHeaderParams || !isObject(contextHeaderParams)) {
+ else if (!contextHeaderParams || !isObject(contextHeaderParams)) {
contextHeaderParams = {"action": "create"};
}
var config = {
@@ -1376,7 +1380,15 @@
var referenceWithoutPaging = _referenceCopy(ownReference);
referenceWithoutPaging.location.beforeObject = null;
- contextHeaderParams.action = action + "/correct-page";
+ // remove the function and replace it with auto-reload
+ var actionVerb = action.substring(action.lastIndexOf(";")+1),
+ newActionVerb = "auto-reload";
+
+ // TODO (could be optimized)
+ if (["load-domain", "reload-domain"].indexOf(actionVerb) !== -1) {
+ newActionVerb = "auto-reload-domain";
+ }
+ contextHeaderParams.action = action.substring(0,action.lastIndexOf(";")+1) + newActionVerb;
referenceWithoutPaging.read(limit, contextHeaderParams, useEntity, true).then(function rereadReference(rereadPage) {
defer.resolve(rereadPage);
}, function error(response) {
@@ -1662,9 +1674,28 @@
uri += module._fixedEncodeURIComponent(columnProjections[k]) + newAlias + ":=" + module._fixedEncodeURIComponent(columnProjections[k]);
}
- if (!contextHeaderParams || !isObject(contextHeaderParams)) {
+ /**
+ * We are going to add the following to the last element of stack in the logs:
+ * {
+ * "num_updated": "number of updated rows"
+ * }
+ */
+ if (isObject(contextHeaderParams) && Array.isArray(contextHeaderParams.stack)) {
+ var stack = contextHeaderParams.stack, numUpdated = submissionData.length;
+ stack[stack.length-1].num_updated = numUpdated;
+
+ stack[stack.length-1].updated_keys = {
+ cols: shortestKeyNames,
+ vals: allNewData.map(function (d) {
+ return shortestKeyNames.map(function (kname) {
+ return d[kname];
+ });
+ })
+ };
+ } else if (!contextHeaderParams || !isObject(contextHeaderParams)) {
contextHeaderParams = {"action": "update"};
}
+
var config = {
headers: this._generateContextHeader(contextHeaderParams, submissionData.length)
};
@@ -2213,13 +2244,33 @@
/**
* The default information that we want to be logged. This includes:
- * - catalog, schema_table, cfacet, cfacet_str, cfacet_path, facets
+ * - catalog, schema_table
+ * TODO Evaluate whether we even need this function
* @type {Object}
*/
get defaultLogInfo() {
var obj = {};
obj.catalog = this.table.schema.catalog.id;
obj.schema_table = this.table.schema.name + ":" + this.table.name;
+ return obj;
+ },
+
+ /**
+ * The object that can be logged to capture the filter state of the reference.
+ * The return object can have:
+ * - filters: the facet object.
+ * - custom_filters:
+ * - the filter strings that parser couldn't turn to facet.
+ * - if we could turn the custom filter to facet, this will return `true`
+ * - cfacet: if there's a cfacet it will be 1
+ * - cfacet_str: if cfacet=1, it will be displayname of cfacet.
+ * - cfacet_path: if cfacet=1, it will be ermrest path of cfacet.
+ * This function creates a new object everytime that it's called, so it
+ * can be manipulated further.
+ * @type {Object}
+ */
+ get filterLogInfo() {
+ var obj = {};
// custom facet
if (this.location.customFacets) {
@@ -2233,15 +2284,15 @@
}
if (this.location.facets) {
- obj.facet = this.location.facets.decoded;
+ obj.filters = _compressFacetObject(this.location.facets.decoded);
} else if (this.location.filter) {
if (this.location.filter.facet) {
- obj.facet = this.location.filter.facet;
+ obj.filters = _compressFacetObject(this.location.filter.facet);
+ obj.custom_filters = true;
} else {
- obj.filter = this.location.filtersString;
+ obj.custom_filters = this.location.filtersString;
}
}
-
return obj;
},
@@ -3318,7 +3369,7 @@
* 0.2 parentDisplayname: the displayname of parent
* - logic: foriengkey's to_name or this.displayname
* 0.3 mainTuple: the tuple used to generate the related references (might be undefined)
- * 0.4 dataSource: the source path from the main to the related table (might be undefined)
+ * 0.4 compressedDataSource: the compressed source path from the main to the related table (might be undefined)
*
* 1. If it's pure and binary association. (current reference: T1) <-F1-(A)-F2-> (T2)
* 1.1 displayname: F2.to_name or T2.displayname
@@ -3412,11 +3463,6 @@
newRef._location = module.parse(this._location.compactUri + "/" + fkr.toString() + "/" + otherFK.toString(true), catalog);
}
- // build the filter source
- filterSource.push({"inbound": otherFK.constraint_names[0]});
-
- // buld the data source
- dataSource.push({"outbound": otherFK.constraint_names[0]});
// additional values for sorting related references
newRef._related_key_column_positions = fkr.key.colset._getColumnPositions();
@@ -3428,6 +3474,11 @@
newRef.derivedAssociationReference.origFKR = newRef.origFKR;
newRef.derivedAssociationReference._secondFKR = otherFK;
+ // build the filter source
+ filterSource.push({"inbound": otherFK.constraint_names[0]});
+
+ // buld the data source
+ dataSource.push({"outbound": otherFK.constraint_names[0]});
} else { // Simple inbound Table
newRef._table = fkrTable;
newRef._shortestKey = newRef._table.shortestKey;
@@ -3458,13 +3509,15 @@
};
}
- // attach the dataSource
if (sourceObject && sourceObject.source) {
- newRef.dataSource = sourceObject.source;
+ dataSource = sourceObject.source;
} else if (newRef._table.shortestKey.length === 1) {
- newRef.dataSource = dataSource.concat(newRef._table.shortestKey[0].name);
+ dataSource = dataSource.concat(newRef._table.shortestKey[0].name);
}
+ // attach the compressedDataSource
+ newRef.compressedDataSource = _compressSource(dataSource);
+
// complete the path
filterSource.push({"outbound": fkr.constraint_names[0]});
@@ -3504,10 +3557,6 @@
contextHeaderParams[key] = this.defaultLogInfo[key];
}
- if (isInteger(page_size)) {
- contextHeaderParams.page_size = page_size;
- }
-
var headers = {};
headers[module.contextHeaderName] = contextHeaderParams;
return headers;
diff --git a/js/setup/node.js b/js/setup/node.js
index 4e3214760..7f0612331 100644
--- a/js/setup/node.js
+++ b/js/setup/node.js
@@ -199,3 +199,14 @@ ERMrest.onload = function() {
return defer.promise;
};
+
+
+var startTime = Date.now();
+/**
+ * @function
+ * @returns {integer} A value set to determine the elapsed time
+ * since the ermrestJS has been available (milliseconds).
+ */
+ERMrest.getElapsedTime = function () {
+ return Date.now() - startTime;
+};
diff --git a/js/utils/constants.js b/js/utils/constants.js
index 596077a4b..9d8edd505 100644
--- a/js/utils/constants.js
+++ b/js/utils/constants.js
@@ -10,6 +10,12 @@
}
}
+ /**
+ * @desc Maximum allowed length of the context header that ermrestjs sends with each request.
+ * If the length of a context heeader goes over the limit, we will try to truncate it.
+ */
+ module.CONTEXT_HEADER_LENGTH_LIMIT = 6500;
+
module._constraintTypes = Object.freeze({
KEY: "k",
FOREIGN_KEY: "fk"
@@ -278,3 +284,13 @@
module._specialSourceDefinitions = Object.freeze({
SEARCH_BOX: "search-box"
});
+
+ module._shorterVersion = Object.freeze({
+ "inbound": "i",
+ "outbound": "o",
+ "source": "src",
+ "sourcekey": "key",
+ "choices": "ch",
+ "ranges": "r",
+ "search": "s"
+ });
diff --git a/js/utils/helpers.js b/js/utils/helpers.js
index 6bfcb4e6a..f7556a318 100644
--- a/js/utils/helpers.js
+++ b/js/utils/helpers.js
@@ -119,6 +119,23 @@
}
};
+ /**
+ * Given an object and two string (k1, k2), if object has k1 key, will
+ * rename that key to k2 instead (values that were accessible through k1
+ * key name will be moved to k2 instead)
+ * @param {Object} obj
+ * @param {String} oldKey
+ * @param {String} newKey
+ */
+ var renameKey = function (obj, oldKey, newKey) {
+ if (!isObjectAndNotNull(obj)) return;
+ if (oldKey === newKey) return;
+ if (!obj.hasOwnProperty(oldKey)) return;
+
+ Object.defineProperty(obj, newKey, Object.getOwnPropertyDescriptor(obj, oldKey));
+ delete obj[oldKey];
+ };
+
/**
* Check if object has all the keys in the given array
* @param {Object} obj the object
@@ -2928,7 +2945,8 @@
module._constraintNames[catalogId][schemaName][constraintName] = {
"subject": subject,
"object": obj,
- "code": "c" + (consIndex++)
+ "code": "c" + (consIndex++),
+ "RID": obj.RID
};
};
@@ -3037,216 +3055,183 @@
};
/**
- * Given a header value, will encode and truncate if its length is more than the allowed length.
- * If the output has `"t":1`, then it has been truncated.
- * These are the allowed and expected values in a header (in order or priority):
- * - cid
- * - pid
- * - wid
- * - schema_table: schema:table
- * - catalog
- * - cqp (chaise query parameter): 1, cfacet: 1, ppid, pcid
- * - template
- * - referrer: for related entities the main entity, for recordset facets: the main entity
- * - schema_table
- * - cfacet_str
- * - cfacet_path
- * - filter
- * - facet
- * - source: the source object of facet
- * - column
- * - cfacet_str
- * - cfacet_path
- * - filter
- * - facet
- *
- * The truncation logic is as follows:
- * 1. if the encoded string is not more than the limit, don't truncate.
+ * @private
+ * @desc
+ * Given a header object, will encode and if neccessary truncate it.
+ * Maximum allowed length of a header after encoding: 6500 characters.
+ * The logic is as follows:
+ * 1. If the encoded string is not lengthy, return it.
* 2. otherwise,
- * 2.1. create the bare minimum log object with the following attributes:
- * - t: 1
- * - cid, wid, pid, action, catalog, schema_table
- * - if cfacet exists: cfacet
- * 2.2. Add other attributes step by step and check the limit. The following
- * is the priority list:
- * - referrer.schema_table, referrer.cfacet, referrer.filter, referrer.facet
- * - source
- * - column
- * - filter, facet, cfacet
+ * 2.1. Return an empty object if the minimal header (defined below) goes over the limit.
+ * 2.2. Otherwise start truncating `stack` object by doing the following. In each step,
+ * if the encoded and truncated header goes below the length limit, return it.
+ * - replace all foreign key constraints with their RIDs (if RID is defined for all of them).
+ * - replace values (`choices`, `ranges`, `search`) in the filters with the number of values.
+ * - replace all `filters.and` with the number of filters.
+ * - replace all source paths with the number of path nodes.
+ * - use replace stack value with the number of stack nodes.
+ * If after performing all these steps, the header is still lengthy, return the minimal header.
+ *
+ * A minimal header will have the following attributes:
+ * - cid, pid, wid, action, schema_table, catalog, t:1
+ * And might have these optional attributes:
+ * - elapsed_ms, cqp, ppid, pcid
*
- * @param {object} header The header content
+ * @param {object} header - the header context
* @return {object}
*/
module._certifyContextHeader = function (header) {
- var MAX_LENGTH = 6500;
- var encode = module._encodeHeaderContent;
- var res = encode(header), prevRes, facetRes;
+ var MAX_LENGTH = module.CONTEXT_HEADER_LENGTH_LIMIT;
+
+ var shorter = module._shorterVersion;
+ var replaceConstraintWithRID = function (src, noRID) {
+ if (noRID) return false;
+
+ var o = shorter.outbound, i = shorter.inbound, fk;
+ if (Array.isArray(srcs)) {
+ src.forEach(function (srcNode) {
+ if (noRID) return;
+ [shorter.outbound, shorter.inbound].forEach(function (direction) {
+ if (noRID) return;
+
+ if (Array.isArray(srcNode[direction])) {
+ fk = module._getConstraintObject(catalog, srcNode[direction][0], srcNode[direction][1]);
+ if (fk && fk.RID) {
+ srcNode[direction] = fk.RID;
+ } else {
+ noRID = true;
+ return;
+ }
+ }
+ });
+ });
+ }
+
+ return !noRID;
+ };
+
+ var encode = module._encodeHeaderContent, i;
+
+ var res = encode(header);
if (res.length < MAX_LENGTH) {
return res;
}
- // the minimal required attributes for log
- var obj = {
+ var catalog = header.catalog;
+ var minimalObj = {
cid: header.cid,
wid: header.wid,
pid: header.pid,
- action: header.action,
catalog: header.catalog,
schema_table: header.schema_table,
- t: 1 // indicates that this request has been truncated
+ action: header.action,
+ t: 1
};
// these attributes might not be available on the header, but if they
// are, we must include them in the minimal header content
- ['cqp', 'cfacet', 'ppid', 'pcid'].forEach(function (attr) {
+ ['elapsed_ms', 'cqp', 'ppid', 'pcid'].forEach(function (attr) {
if (header[attr]) {
- obj[attr] = header[attr];
+ minimalObj[attr] = header[attr];
}
});
- prevRes = res = encode(obj);
- if (res.length >= MAX_LENGTH) {
+ // if even minimal is bigger than the limit, don't log anything
+ if (encode(minimalObj).length >= MAX_LENGTH) {
return {};
}
- // truncate cfacet, facet, or filter
- // if it's a facet that has `and` in the first level,
- // it will remove only the array element that is needed. otherwise
- // the whole facet/filter will be removed.
- var truncateFacet = function (obj, header, key) {
- var prevRes = encode(obj);
- var h = key ? header[key] : header;
+ // truncation is based on stack, if there's no stack, just log the minimal object
+ if (!Array.isArray(header.stack)) {
+ return minimalObj;
+ }
- var setObjAndEncode = function (attr) {
- if (key) {
- obj[key][attr] = h[attr];
- } else {
- obj[attr] = h[attr];
- }
- return encode(obj);
- };
+ var truncated = module._simpleDeepCopy(header);
- if (h.cfacet_str) {
- res = setObjAndEncode("cfacet_str");
- if (res.length >= MAX_LENGTH) {
- return {truncated: true, res: prevRes};
- }
- prevRes = res;
- }
-
- if (h.cfacet_path) {
- res = setObjAndEncode("cfacet_str");
- if (res.length >= MAX_LENGTH) {
- return {truncated: true, res: prevRes};
- }
- prevRes = res;
- }
+ // replace all fk constraints with their RID
+ // if RID is not available on even one fk, we will not replacing any of RIDs
+ // and go to the next step.
+ var noRID = false;
+ truncated.stack.forEach(function (stackEl) {
+ if (noRID) return;
- if (h.filter) {
- // add filter
- res = setObjAndEncode("filter");
- if (res.length >= MAX_LENGTH) {
- // it was lengthy so just return the obj without filter
- return {truncated: true, res: prevRes};
- }
+ // filters
+ if (stackEl.filters && Array.isArray(stackEl.filters.and)) {
+ stackEl.filters.and.forEach(function (facet) {
+ if (noRID) return;
- // return result with filter
- return {truncated: false, res: res};
+ if (Array.isArray(facet[shorter.source])) {
+ noRID = !replaceConstraintWithRID(facet[shorter.source]);
+ }
+ });
}
- // this function only expects cfacet, facet, and filter. it will ignore other variables
- if (!h.facet) {
- return {truncated: false, res: prevRes};
+ // sources
+ if (stackEl.source && Array.isArray(stackEl.source)) {
+ noRID = !replaceConstraintWithRID(stackEl.source);
}
+ });
- // only optimized for just one type of facet that we currently support: {and: []}
- // otherwise just treat it as a object
- if (!Array.isArray(h.facet.and)) {
-
- // add the facet
- res = setObjAndEncode("filter");
- if (res.length >= MAX_LENGTH) {
- return {truncated: true, res: prevRes};
- }
-
- // return result with facet
- return {truncated: true, res: res};
- }
+ if (noRID) {
+ truncated = module._simpleDeepCopy(header);
+ } else {
+ res = encode(truncated);
+ if (res.length < MAX_LENGTH) {
+ return res;
+ }
+ }
- if (key) {
- obj[key].facet = {and: []};
- } else {
- obj.facet = {and: []};
+ // replace choices, ranges, search with number of values
+ truncated.stack.forEach(function (stackEl) {
+ if (stackEl.filters && Array.isArray(stackEl.filters.and)) {
+ stackEl.filters.and.forEach(function (facet) {
+ [shorter.choices, shorter.ranges, shorter.search].forEach(function (k) {
+ facet[k] = Array.isArray(facet[k]) ? facet[k].length : 1;
+ });
+ });
}
+ });
- // add fitlers in the and array one by one until getting to the limit.
- for (var i = 0; i < h.facet.and.length; i++) {
- if (key) {
- obj[key].facet.and.push(h.facet.and[i]);
- } else {
- obj.facet.and.push(h.facet.and[i]);
- }
+ res = encode(truncated);
+ if (res.length < MAX_LENGTH) {
+ return res;
+ }
- res = encode(obj);
- if (res.length >= MAX_LENGTH) {
- return {truncated: true, res: prevRes};
- }
- prevRes = res;
+ // replace all filters.and with the number of filters
+ truncated.stack.forEach(function (stackEl) {
+ if (stackEl.filters && Array.isArray(stackEl.filters.and)) {
+ stackEl.filters.and = stackEl.filters.and.length;
}
+ });
- // this means that the object had other attributes (apart from filter and facet)
- // which is getting truncated
- return {truncated: true, res: res};
- };
-
- // template
- if (header.template) {
- obj.template = header.template;
- res = encode(obj);
- if (res.length >= MAX_LENGTH) {
- return prevRes;
- }
+ res = encode(truncated);
+ if (res.length < MAX_LENGTH) {
+ return res;
}
- // referrer: schema_table, facet (filter)
- if (header.referrer) {
- obj.referrer = {
- schema_table: header.referrer.schema_table
- };
- res = encode(obj);
- if (res.length >= MAX_LENGTH) {
- return prevRes;
+ // replace all source paths with the number of path nodes
+ truncated.stack.forEach(function (stackEl) {
+ if (stackEl.source) {
+ stackEl.source = Array.isArray(stackEl.source) ? stackEl.source.length : 1;
}
+ });
- // take care of facet and fitler in referrer
- facetRes = truncateFacet(obj, header, "referrer");
- if (facetRes.truncated) {
- return facetRes.res;
- }
- prevRes = facetRes.res;
+ res = encode(truncated);
+ if (res.length < MAX_LENGTH) {
+ return res;
}
- // .source
- if (header.source) {
- obj.source = header.source;
- res = encode(obj);
- if (res.length >= MAX_LENGTH) {
- return prevRes;
- }
- }
+ // replace stack with the number of elements
+ truncated.stack = truncated.stack.length;
- // .column
- if (header.column) {
- obj.column = header.column;
- res = encode(obj);
- if (res.length >= MAX_LENGTH) {
- return prevRes;
- }
+ res = encode(truncated);
+ if (res.length < MAX_LENGTH) {
+ return res;
}
- // take care of facet and fitler
- return truncateFacet(obj, header).res;
+ // if none of the truncation works, just return the minimal obj
+ return encode(minimalObj);
};
module._isEntryContext = function(context) {
diff --git a/js/utils/polyfills.js b/js/utils/polyfills.js
index 72d03b59e..01d03c5f5 100644
--- a/js/utils/polyfills.js
+++ b/js/utils/polyfills.js
@@ -254,3 +254,10 @@ String.prototype.replaceAll = function(search, replacement) {
Array.prototype.clear = function() {
this.length = 0;
};
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
+Number.isInteger = Number.isInteger || function(value) {
+ return typeof value === 'number' &&
+ isFinite(value) &&
+ Math.floor(value) === value;
+};
diff --git a/js/utils/pseudocolumn_helpers.js b/js/utils/pseudocolumn_helpers.js
index 53dc2baf9..f7efb2c4f 100644
--- a/js/utils/pseudocolumn_helpers.js
+++ b/js/utils/pseudocolumn_helpers.js
@@ -835,3 +835,70 @@
return returnError("Invalid column name in source");
}
};
+
+ /**
+ * @private
+ * @param {Object} source the source array or string
+ * @desc
+ * Will compress the source that can be used for logging purposes. It will,
+ * - `inbound` to `i`
+ * - `outbound` to `o`
+ */
+ _compressSource = function (source) {
+ if (!source) return source;
+
+ var res = module._simpleDeepCopy(source);
+ var shorter = module._shorterVersion;
+
+ if (!_sourceHasPath(source)) return res;
+
+ for (var i = 0; i < res.length; i++) {
+ renameKey(res[i], "inbound", shorter.inbound);
+ renameKey(res[i], "outbound", shorter.outbound);
+ }
+ return res;
+ };
+
+ /**
+ * @private
+ * @param {Object} facet the facet object
+ * Given a facet will compress it so it can be used for logging purposes, it will,
+ * - `inbound` to `i`
+ * - `outbound` to `o`
+ * - `source` to `src`
+ * - `sourcekey` to `key`
+ * - `choices` to `ch`
+ * - `ranges` to `r`
+ * - `search` to `s`
+ * NOTE: This function supports combination of conjunction and disjunction.
+ */
+ _compressFacetObject = function (facet) {
+ var res = module._simpleDeepCopy(facet),
+ and = module._FacetsLogicalOperators.AND,
+ or = module._FacetsLogicalOperators.OR,
+ shorter = module._shorterVersion;
+
+ var shorten = function (node) {
+ return function (k) {
+ renameKey(node, k, shorter[k]);
+ };
+ };
+
+ var compressRec = function (node) {
+ if ("source" in node) {
+ node.src = _compressSource(node.source);
+ delete node.source;
+
+ ["choices", "ranges", "search", "sourcekey"].forEach(shorten(node));
+ } else {
+ [and, or].forEach(function (operator) {
+ if (!Array.isArray(node[operator])) return;
+
+ node[operator].forEach(compressRec);
+ });
+ }
+ };
+
+ compressRec(res);
+ return res;
+ };
diff --git a/test/specs/column/tests/02.reference_column.js b/test/specs/column/tests/02.reference_column.js
index a0e212341..3bd76090a 100644
--- a/test/specs/column/tests/02.reference_column.js
+++ b/test/specs/column/tests/02.reference_column.js
@@ -73,12 +73,12 @@ exports.execute = function (options) {
// NOTE relies on the heuristics
// needs to be adjusted if we change the heuristics
- var expectedDataSources = [
+ var expectedCompressedDataSources = [
"id",
- [{"outbound": ["columns_schema", "outbound_fk_1"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_2"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_3"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_4"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_1"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_2"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_3"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_4"]}, "RID"],
"col_3",
"col_4",
"col 5",
@@ -91,11 +91,11 @@ exports.execute = function (options) {
"RMT",
"RCB",
"RMB",
- [{"outbound": ["columns_schema", "outbound_fk_5"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_6"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_8"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_7"]}, "RID"],
- [{"outbound": ["columns_schema", "outbound_fk_9"]}, "RID"]
+ [{"o": ["columns_schema", "outbound_fk_5"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_6"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_8"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_7"]}, "RID"],
+ [{"o": ["columns_schema", "outbound_fk_9"]}, "RID"]
];
@@ -259,10 +259,10 @@ exports.execute = function (options) {
});
- describe("dataSource, ", function () {
+ describe("compressedDataSource, ", function () {
it ("should return the correct value for all the different column types.", function () {
compactColumns.forEach(function (col, index) {
- expect(col.dataSource).toEqual(expectedDataSources[index], "missmatch for index=" + index);
+ expect(col.compressedDataSource).toEqual(expectedCompressedDataSources[index], "missmatch for index=" + index);
});
});
})
diff --git a/test/specs/column/tests/03.pseudo_column.js b/test/specs/column/tests/03.pseudo_column.js
index 2979a5f73..aa9cde959 100644
--- a/test/specs/column/tests/03.pseudo_column.js
+++ b/test/specs/column/tests/03.pseudo_column.js
@@ -446,38 +446,38 @@ exports.execute = function (options) {
// (ForeignKey, InboundforeignKey, etc.) to the shortestkey.
expect(facetColumns.length).toBe(12, "length missmatch.");
expect(facetColumns.map(function (fc) {
- return fc.dataSource;
+ return fc.compressedDataSource;
})).toEqual(
[
"main_table_id_col", "col", "main_table_id_col", // the key
- [{"outbound": ["pseudo_column_schema", "main_fk1"]}, "RID"],
- [{"outbound": ["pseudo_column_schema", "main_fk1"]}, "id"], //entity:false
+ [{"o": ["pseudo_column_schema", "main_fk1"]}, "RID"],
+ [{"o": ["pseudo_column_schema", "main_fk1"]}, "id"], //entity:false
[
- {"outbound": ["pseudo_column_schema", "main_fk1"]},
- {"outbound": ["pseudo_column_schema", "outbound_1_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk1"]},
+ {"o": ["pseudo_column_schema", "outbound_1_fk1"]},
"id"
],
[
- {"outbound": ["pseudo_column_schema", "main_fk1"]},
- {"outbound": ["pseudo_column_schema", "outbound_1_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk1"]},
+ {"o": ["pseudo_column_schema", "outbound_1_fk1"]},
"id"
],
"asset_filename",
[
- {"outbound": ["pseudo_column_schema", "main_fk2"]},
- {"outbound": ["pseudo_column_schema", "outbound_2_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk2"]},
+ {"o": ["pseudo_column_schema", "outbound_2_fk1"]},
"id"
],
- [{"inbound": ["pseudo_column_schema", "inbound_3_outbound_1_fk1"]}, "RID"],
+ [{"i": ["pseudo_column_schema", "inbound_3_outbound_1_fk1"]}, "RID"],
[
- {"inbound": ["pseudo_column_schema", "main_inbound_3_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_3_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_3_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_3_association_fk2"]},
"RID"
],
[
- {"inbound": ["pseudo_column_schema", "main_inbound_3_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_3_association_fk2"]},
- {"outbound": ["pseudo_column_schema", "inbound_3_fk1"]},
+ {"i": ["pseudo_column_schema", "main_inbound_3_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_3_association_fk2"]},
+ {"o": ["pseudo_column_schema", "inbound_3_fk1"]},
"id"
]
],
@@ -671,102 +671,102 @@ exports.execute = function (options) {
});
});
- describe("dataSource, ", function () {
- var detailedColumnDataSources = [
+ describe("compressedDataSource, ", function () {
+ var detailedColumnCompressedDataSources = [
"main_table_id_col", //0
"col", //1
"main_table_id_col", //2
- [{"outbound": ["pseudo_column_schema", "main_fk1"]}, "id"], //3
- [{"outbound": ["pseudo_column_schema", "main_fk1"]}, "id"], //4
+ [{"o": ["pseudo_column_schema", "main_fk1"]}, "id"], //3
+ [{"o": ["pseudo_column_schema", "main_fk1"]}, "id"], //4
[
- {"outbound": ["pseudo_column_schema", "main_fk1"]},
- {"outbound": ["pseudo_column_schema", "outbound_1_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk1"]},
+ {"o": ["pseudo_column_schema", "outbound_1_fk1"]},
"id"
], //5
[
- {"outbound": ["pseudo_column_schema", "main_fk1"]},
- {"outbound": ["pseudo_column_schema", "outbound_1_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk1"]},
+ {"o": ["pseudo_column_schema", "outbound_1_fk1"]},
"id"
], //6
- [{"inbound": ["pseudo_column_schema", "inbound_1_fk1"]}, "id"], //7
+ [{"i": ["pseudo_column_schema", "inbound_1_fk1"]}, "id"], //7
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
"id"
], //8
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
- {"outbound": ["pseudo_column_schema", "inbound_2_fk1"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"o": ["pseudo_column_schema", "inbound_2_fk1"]},
"id"
], //9
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]}, "id"
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]}, "id"
], //10
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
"id"
], //11
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
- {"outbound": ["pseudo_column_schema", "inbound_2_fk1"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"o": ["pseudo_column_schema", "inbound_2_fk1"]},
"id"
], //12
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]}, "id"
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]}, "id"
], //13
"col", //14
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
"id"
], //15
[
- { "inbound": [ "pseudo_column_schema", "main_inbound_2_association_fk1"]},
- { "outbound": [ "pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ { "i": [ "pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ { "o": [ "pseudo_column_schema", "main_inbound_2_association_fk2"]},
"id"
], //16
[
- { "inbound": [ "pseudo_column_schema", "main_inbound_2_association_fk1"]},
- { "outbound": [ "pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ { "i": [ "pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ { "o": [ "pseudo_column_schema", "main_inbound_2_association_fk2"]},
"id"
], //17
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
"id"
], //18
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
"RID"
], //19
[
- {"inbound": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
- {"outbound": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
+ {"i": ["pseudo_column_schema", "main_inbound_2_association_fk1"]},
+ {"o": ["pseudo_column_schema", "main_inbound_2_association_fk2"]},
"timestamp_col"
], //20
[
- {"inbound": ["pseudo_column_schema", "inbound_4_long_table_name_fk"]}, "foreign key column name to main"
+ {"i": ["pseudo_column_schema", "inbound_4_long_table_name_fk"]}, "foreign key column name to main"
], //21
"asset", //22
"asset_filename", //23
[
- {"outbound": ["pseudo_column_schema", "main_fk2"]},
- {"inbound": ["pseudo_column_schema", "outbound_2_inbound_1_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk2"]},
+ {"i": ["pseudo_column_schema", "outbound_2_inbound_1_fk1"]},
"id"
], //24
[
- {"outbound": ["pseudo_column_schema", "main_fk2"]},
- {"outbound": ["pseudo_column_schema", "outbound_2_fk1"]},
+ {"o": ["pseudo_column_schema", "main_fk2"]},
+ {"o": ["pseudo_column_schema", "outbound_2_fk1"]},
"id"
] //25
];
it ("should return the data source of the pseudo-column.", function () {
detailedColsWTuple.forEach(function (col, index) {
- expect(col.dataSource).toEqual(detailedColumnDataSources[index], "missmatch for index=" + index);
+ expect(col.compressedDataSource).toEqual(detailedColumnCompressedDataSources[index], "missmatch for index=" + index);
});
});
})
diff --git a/test/specs/reference/tests/02.related_reference.js b/test/specs/reference/tests/02.related_reference.js
index 778687f8e..2f26eb3ee 100644
--- a/test/specs/reference/tests/02.related_reference.js
+++ b/test/specs/reference/tests/02.related_reference.js
@@ -199,54 +199,54 @@ exports.execute = function(options) {
expect(related[3].origFKR.toString()).toBe('(id)=(reference_schema:association%20table%20with%20id:id%20from%20ref%20table)');
});
- it ('.dataSource should have the correct value', function () {
- var expectedDataSources = [
- [{"inbound": ["reference_schema", "fromname_fk_inbound_related_to_reference"]}, "RID"],
- [{"inbound": ["reference_schema", "fk_inbound_related_to_reference"]}, "id"],
+ it ('.compressedDataSource should have the correct value', function () {
+ var expectedCompressedDataSources = [
+ [{"i": ["reference_schema", "fromname_fk_inbound_related_to_reference"]}, "RID"],
+ [{"i": ["reference_schema", "fk_inbound_related_to_reference"]}, "id"],
[
- {"inbound": ["reference_schema", "toname_fk_association_related_to_reference"]},
- {"outbound": ["reference_schema", "association_table_with_toname_id_from_inbound_related_table1"]},
+ {"i": ["reference_schema", "toname_fk_association_related_to_reference"]},
+ {"o": ["reference_schema", "association_table_with_toname_id_from_inbound_related_table1"]},
"RID"
],
[
- {"inbound": ["reference_schema", "id_fk_association_related_to_reference"]},
- {"outbound": ["reference_schema", "fk_to_inbound_related_reference_table"]},
+ {"i": ["reference_schema", "id_fk_association_related_to_reference"]},
+ {"o": ["reference_schema", "fk_to_inbound_related_reference_table"]},
"id"
],
[
- {"inbound": ["reference_schema", "system_col_fk_asscoation_related_to_reference"]},
- {"outbound": ["reference_schema", "association_table_with_system_col_fk_fk2"]},
+ {"i": ["reference_schema", "system_col_fk_asscoation_related_to_reference"]},
+ {"o": ["reference_schema", "association_table_with_system_col_fk_fk2"]},
"RID"
],
[
- {"inbound": ["reference_schema", "extra_fk_association_related_to_reference"]},
+ {"i": ["reference_schema", "extra_fk_association_related_to_reference"]},
"RID"
]
];
related.forEach(function (rel, i) {
- expect(related[i].dataSource).toEqual(expectedDataSources[i], "missmatch for index=" + i);
+ expect(related[i].compressedDataSource).toEqual(expectedCompressedDataSources[i], "missmatch for index=" + i);
});
});
describe("for related tables using source path.", function () {
// what about other APIs?
- it (".dataSource should have the correct value.", function () {
- var expectedDataSources = [
- [{"inbound": ["reference_schema", "id_fk_association_related_to_reference"]}, "ID"],
+ it (".compressedDataSource should have the correct value.", function () {
+ var expectedCompressedDataSources = [
+ [{"i": ["reference_schema", "id_fk_association_related_to_reference"]}, "ID"],
[
- {"inbound": ["reference_schema", "id_fk_association_related_to_reference"]},
- {"outbound": ["reference_schema", "fk_to_inbound_related_reference_table"]},
- {"outbound": ["reference_schema", "fromname_fk_inbound_related_to_reference"]},
+ {"i": ["reference_schema", "id_fk_association_related_to_reference"]},
+ {"o": ["reference_schema", "fk_to_inbound_related_reference_table"]},
+ {"o": ["reference_schema", "fromname_fk_inbound_related_to_reference"]},
"id"
],
[
- {"outbound": ["reference_schema", "reference_table_fk1"]},
- {"inbound": ["reference_schema", "reference_outbound_1_inbound_1_fk1"]},
+ {"o": ["reference_schema", "reference_table_fk1"]},
+ {"i": ["reference_schema", "reference_outbound_1_inbound_1_fk1"]},
"id"
]
];
pathRelatedWithTuple.forEach(function (rel, i) {
- expect(rel.dataSource).toEqual(expectedDataSources[i], "missmatch for index=" + i);
+ expect(rel.compressedDataSource).toEqual(expectedCompressedDataSources[i], "missmatch for index=" + i);
});
});
});