apache-arrow
Version:
Apache Arrow columnar in-memory format
138 lines (136 loc) • 5.77 kB
JavaScript
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import { MetadataVersion } from './enum.mjs';
import { DataType } from './type.mjs';
export class Schema {
constructor(fields = [], metadata, dictionaries, metadataVersion = MetadataVersion.V5) {
this.fields = (fields || []);
this.metadata = metadata || new Map();
if (!dictionaries) {
dictionaries = generateDictionaryMap(this.fields);
}
this.dictionaries = dictionaries;
this.metadataVersion = metadataVersion;
}
get [Symbol.toStringTag]() { return 'Schema'; }
get names() { return this.fields.map((f) => f.name); }
toString() {
return `Schema<{ ${this.fields.map((f, i) => `${i}: ${f}`).join(', ')} }>`;
}
/**
* Construct a new Schema containing only specified fields.
*
* @param fieldNames Names of fields to keep.
* @returns A new Schema of fields matching the specified names.
*/
select(fieldNames) {
const names = new Set(fieldNames);
const fields = this.fields.filter((f) => names.has(f.name));
return new Schema(fields, this.metadata);
}
/**
* Construct a new Schema containing only fields at the specified indices.
*
* @param fieldIndices Indices of fields to keep.
* @returns A new Schema of fields at the specified indices.
*/
selectAt(fieldIndices) {
const fields = fieldIndices.map((i) => this.fields[i]).filter(Boolean);
return new Schema(fields, this.metadata);
}
assign(...args) {
const other = (args[0] instanceof Schema
? args[0]
: Array.isArray(args[0])
? new Schema(args[0])
: new Schema(args));
const curFields = [...this.fields];
const metadata = mergeMaps(mergeMaps(new Map(), this.metadata), other.metadata);
const newFields = other.fields.filter((f2) => {
const i = curFields.findIndex((f) => f.name === f2.name);
return ~i ? (curFields[i] = f2.clone({
metadata: mergeMaps(mergeMaps(new Map(), curFields[i].metadata), f2.metadata)
})) && false : true;
});
const newDictionaries = generateDictionaryMap(newFields, new Map());
return new Schema([...curFields, ...newFields], metadata, new Map([...this.dictionaries, ...newDictionaries]));
}
}
// Add these here so they're picked up by the externs creator
// in the build, and closure-compiler doesn't minify them away
Schema.prototype.fields = null;
Schema.prototype.metadata = null;
Schema.prototype.dictionaries = null;
export class Field {
/** @nocollapse */
static new(...args) {
let [name, type, nullable, metadata] = args;
if (args[0] && typeof args[0] === 'object') {
({ name } = args[0]);
(type === undefined) && (type = args[0].type);
(nullable === undefined) && (nullable = args[0].nullable);
(metadata === undefined) && (metadata = args[0].metadata);
}
return new Field(`${name}`, type, nullable, metadata);
}
constructor(name, type, nullable = false, metadata) {
this.name = name;
this.type = type;
this.nullable = nullable;
this.metadata = metadata || new Map();
}
get typeId() { return this.type.typeId; }
get [Symbol.toStringTag]() { return 'Field'; }
toString() { return `${this.name}: ${this.type}`; }
clone(...args) {
let [name, type, nullable, metadata] = args;
(!args[0] || typeof args[0] !== 'object')
? ([name = this.name, type = this.type, nullable = this.nullable, metadata = this.metadata] = args)
: ({ name = this.name, type = this.type, nullable = this.nullable, metadata = this.metadata } = args[0]);
return Field.new(name, type, nullable, metadata);
}
}
// Add these here so they're picked up by the externs creator
// in the build, and closure-compiler doesn't minify them away
Field.prototype.type = null;
Field.prototype.name = null;
Field.prototype.nullable = null;
Field.prototype.metadata = null;
/** @ignore */
function mergeMaps(m1, m2) {
return new Map([...(m1 || new Map()), ...(m2 || new Map())]);
}
/** @ignore */
function generateDictionaryMap(fields, dictionaries = new Map()) {
for (let i = -1, n = fields.length; ++i < n;) {
const field = fields[i];
const type = field.type;
if (DataType.isDictionary(type)) {
if (!dictionaries.has(type.id)) {
dictionaries.set(type.id, type.dictionary);
}
else if (dictionaries.get(type.id) !== type.dictionary) {
throw new Error(`Cannot create Schema containing two different dictionaries with the same Id`);
}
}
if (type.children && type.children.length > 0) {
generateDictionaryMap(type.children, dictionaries);
}
}
return dictionaries;
}
//# sourceMappingURL=schema.mjs.map