This is an automated email from the ASF dual-hosted git repository.

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new c8d97fa  ARROW-2650: [JS] Implement Unions
c8d97fa is described below

commit c8d97fa92bb45fb090ad155758d88b0d56da0d7e
Author: ptaylor <[email protected]>
AuthorDate: Wed Jul 4 11:10:13 2018 -0400

    ARROW-2650: [JS] Implement Unions
    
    Still need to add Unions to the integration tests, but I validated this 
locally with the [JSON 
file](https://github.com/icexelloss/arrow/blob/2d6d41dbb041dbee06131b3f94a3fae4e0a90fd2/integration/data/union.json)
 from #987 and it seems to work:
    
    ```sh
    $ ./bin/json-to-arrow.js -j ./test/data/json/union.json -a 
./test/data/union-file.arrow
    $ cat ./test/data/union-file.arrow | ./bin/file-to-stream.js > 
./test/data/union-stream.arrow
    $ cat ./test/data/union-file.arrow | node 
./targets/apache-arrow/bin/arrow2csv.js
    "row_id" | "union: Union<Int32 | Int64>"
           0 |                             0
           1 |                         [1,0]
           2 |                             2
           3 |                         [3,0]
           4 |                             4
           5 |                         [5,0]
           6 |                             6
           7 |                         [7,0]
           8 |                             8
           9 |                         [9,0]
    
    $ cat ./test/data/union-stream.arrow | node 
./targets/apache-arrow/bin/arrow2csv.js
    "row_id" | "union: Union<Int32 | Int64>"
           0 |                             0
           1 |                         [1,0]
           2 |                             2
           3 |                         [3,0]
           4 |                             4
           5 |                         [5,0]
           6 |                             6
           7 |                         [7,0]
           8 |                             8
           9 |                         [9,0]
    
    ```
    
    Author: ptaylor <[email protected]>
    
    Closes #2092 from trxcllnt/js-finish-unions and squashes the following 
commits:
    
    9b199c39 <ptaylor> finish implementing unions in the JS reader
    953232c0 <ptaylor> write schema metadata
---
 js/src/data.ts            |  4 ++++
 js/src/ipc/reader/json.ts | 37 ++++++++++++++++++++-----------------
 js/src/type.ts            |  6 ++++--
 js/src/vector/nested.ts   | 28 ++++++++++++++++------------
 4 files changed, 44 insertions(+), 31 deletions(-)

diff --git a/js/src/data.ts b/js/src/data.ts
index 963a6a4..2c79151 100644
--- a/js/src/data.ts
+++ b/js/src/data.ts
@@ -216,9 +216,13 @@ export class ListData<T extends ListType> extends 
SingleNestedData<T> {
 export class UnionData<T extends (DenseUnion | SparseUnion) = any> extends 
NestedData<T> {
     public /*    [VectorType.TYPE]:*/ 3: T['TArray'];
     public get typeIds() { return this[VectorType.TYPE]; }
+    public readonly typeIdToChildIndex: { [key: number]: number };
     constructor(type: T, length: number, nullBitmap: Uint8Array | null | 
undefined, typeIds: Iterable<number>, childData: Data<any>[], offset?: number, 
nullCount?: number) {
         super(type, length, nullBitmap, childData, offset, nullCount);
         this[VectorType.TYPE] = toTypedArray(Int8Array, typeIds);
+        this.typeIdToChildIndex = type.typeIds.reduce((typeIdToChildIndex, 
typeId, idx) => {
+            return (typeIdToChildIndex[typeId] = idx) && typeIdToChildIndex || 
typeIdToChildIndex;
+        }, Object.create(null) as { [key: number]: number });
     }
     public clone<R extends T>(type: R, length = this.length, offset = 
this.offset, nullCount = this._nullCount) {
         return new UnionData<R>(type, length, this[VectorType.VALIDITY], 
this[VectorType.TYPE], this.childData, offset, nullCount);
diff --git a/js/src/ipc/reader/json.ts b/js/src/ipc/reader/json.ts
index 67bb5ca..e8ab498 100644
--- a/js/src/ipc/reader/json.ts
+++ b/js/src/ipc/reader/json.ts
@@ -76,6 +76,7 @@ function flattenDataSources(xs: any[]): any[][] {
         ...buffers,
         ...(column['VALIDITY'] && [column['VALIDITY']] || []),
         ...(column['OFFSET'] && [column['OFFSET']] || []),
+        ...(column['TYPE'] && [column['TYPE']] || []),
         ...(column['DATA'] && [column['DATA']] || []),
         ...flattenDataSources(column['children'])
     ], [] as any[][]);
@@ -156,6 +157,7 @@ import * as Schema_ from '../../fb/Schema';
 import Type = Schema_.org.apache.arrow.flatbuf.Type;
 import DateUnit = Schema_.org.apache.arrow.flatbuf.DateUnit;
 import TimeUnit = Schema_.org.apache.arrow.flatbuf.TimeUnit;
+import UnionMode = Schema_.org.apache.arrow.flatbuf.UnionMode;
 import Precision = Schema_.org.apache.arrow.flatbuf.Precision;
 import IntervalUnit = Schema_.org.apache.arrow.flatbuf.IntervalUnit;
 import MetadataVersion = Schema_.org.apache.arrow.flatbuf.MetadataVersion;
@@ -209,6 +211,7 @@ function buffersFromJSON(xs: any[], buffers: 
BufferMetadata[] = []): BufferMetad
         const column = xs[i];
         column['VALIDITY'] && buffers.push(new BufferMetadata(new 
Long(buffers.length, 0), new Long(column['VALIDITY'].length, 0)));
         column['OFFSET'] && buffers.push(new BufferMetadata(new 
Long(buffers.length, 0), new Long(column['OFFSET'].length, 0)));
+        column['TYPE'] && buffers.push(new BufferMetadata(new 
Long(buffers.length, 0), new Long(column['TYPE'].length, 0)));
         column['DATA'] && buffers.push(new BufferMetadata(new 
Long(buffers.length, 0), new Long(column['DATA'].length, 0)));
         buffers = buffersFromJSON(column['children'], buffers);
     }
@@ -293,31 +296,31 @@ function typeFromJSON(t: any, children?: Field[]) {
     throw new Error(`Unrecognized type ${t['name']}`);
 }
 
-function nullFromJSON           (_type: any)                    { return new 
Null();                                                                  }
+function nullFromJSON           (_type: any)                    { return new 
Null();                                                                         
      }
 function intFromJSON            (_type: any)                    { switch 
(_type['bitWidth']) {
                                                                       case  8: 
return _type['isSigned'] ? new  Int8() : new  Uint8();
                                                                       case 16: 
return _type['isSigned'] ? new Int16() : new Uint16();
                                                                       case 32: 
return _type['isSigned'] ? new Int32() : new Uint32();
                                                                       case 64: 
return _type['isSigned'] ? new Int64() : new Uint64();
                                                                   }
-                                                                  return null; 
                                                                       }
+                                                                  return null; 
                                                                                
    }
 function floatingPointFromJSON  (_type: any)                    { switch 
(Precision[_type['precision']] as any) {
                                                                       case 
Precision.HALF: return new Float16();
                                                                       case 
Precision.SINGLE: return new Float32();
                                                                       case 
Precision.DOUBLE: return new Float64();
                                                                   }
-                                                                  return null; 
                                                                       }
-function binaryFromJSON         (_type: any)                    { return new 
Binary();                                                                }
-function utf8FromJSON           (_type: any)                    { return new 
Utf8();                                                                  }
-function boolFromJSON           (_type: any)                    { return new 
Bool();                                                                  }
-function decimalFromJSON        (_type: any)                    { return new 
Decimal(_type['scale'], _type['precision']);                             }
-function dateFromJSON           (_type: any)                    { return new 
Date_(DateUnit[_type['unit']] as any);                                   }
-function timeFromJSON           (_type: any)                    { return new 
Time(TimeUnit[_type['unit']] as any, _type['bitWidth'] as TimeBitWidth); }
-function timestampFromJSON      (_type: any)                    { return new 
Timestamp(TimeUnit[_type['unit']] as any, _type['timezone']);            }
-function intervalFromJSON       (_type: any)                    { return new 
Interval(IntervalUnit[_type['unit']] as any);                            }
-function listFromJSON           (_type: any, children: Field[]) { return new 
List(children);                                                          }
-function structFromJSON         (_type: any, children: Field[]) { return new 
Struct(children);                                                        }
-function unionFromJSON          (_type: any, children: Field[]) { return new 
Union(_type['mode'], (_type['typeIdsArray'] || []) as Type[], children); }
-function fixedSizeBinaryFromJSON(_type: any)                    { return new 
FixedSizeBinary(_type['byteWidth']);                                     }
-function fixedSizeListFromJSON  (_type: any, children: Field[]) { return new 
FixedSizeList(_type['listSize'], children);                              }
-function mapFromJSON            (_type: any, children: Field[]) { return new 
Map_(_type['keysSorted'], children);                                     }
+                                                                  return null; 
                                                                                
    }
+function binaryFromJSON         (_type: any)                    { return new 
Binary();                                                                       
      }
+function utf8FromJSON           (_type: any)                    { return new 
Utf8();                                                                         
      }
+function boolFromJSON           (_type: any)                    { return new 
Bool();                                                                         
      }
+function decimalFromJSON        (_type: any)                    { return new 
Decimal(_type['scale'], _type['precision']);                                    
      }
+function dateFromJSON           (_type: any)                    { return new 
Date_(DateUnit[_type['unit']] as any);                                          
      }
+function timeFromJSON           (_type: any)                    { return new 
Time(TimeUnit[_type['unit']] as any, _type['bitWidth'] as TimeBitWidth);        
      }
+function timestampFromJSON      (_type: any)                    { return new 
Timestamp(TimeUnit[_type['unit']] as any, _type['timezone']);                   
      }
+function intervalFromJSON       (_type: any)                    { return new 
Interval(IntervalUnit[_type['unit']] as any);                                   
      }
+function listFromJSON           (_type: any, children: Field[]) { return new 
List(children);                                                                 
      }
+function structFromJSON         (_type: any, children: Field[]) { return new 
Struct(children);                                                               
      }
+function unionFromJSON          (_type: any, children: Field[]) { return new 
Union(UnionMode[_type['mode']] as any, (_type['typeIds'] || []) as Type[], 
children); }
+function fixedSizeBinaryFromJSON(_type: any)                    { return new 
FixedSizeBinary(_type['byteWidth']);                                            
      }
+function fixedSizeListFromJSON  (_type: any, children: Field[]) { return new 
FixedSizeList(_type['listSize'], children);                                     
      }
+function mapFromJSON            (_type: any, children: Field[]) { return new 
Map_(_type['keysSorted'], children);                                            
      }
diff --git a/js/src/type.ts b/js/src/type.ts
index 370be0d..26686c7 100644
--- a/js/src/type.ts
+++ b/js/src/type.ts
@@ -372,9 +372,11 @@ export class Union<TType extends Type = any> extends 
DataType<TType> {
     constructor(public readonly mode: UnionMode,
                 public readonly typeIds: ArrowType[],
                 public readonly children: Field[]) {
-        super(<TType> (mode === UnionMode.Sparse ? Type.SparseUnion : 
Type.DenseUnion), children);
+        super(<TType> Type.Union, children);
     }
-    public toString() { return 
`${this[Symbol.toStringTag]}<${this.typeIds.map((x) => Type[x]).join(` | `)}>`; 
}
+    public toString() { return `${this[Symbol.toStringTag]}<${
+        this.children.map((x) => `${x.type}`).join(` | `)
+    }>`; }
     protected static [Symbol.toStringTag] = ((proto: Union) => {
         (<any> proto).ArrayType = Int8Array;
         return proto[Symbol.toStringTag] = 'Union';
diff --git a/js/src/vector/nested.ts b/js/src/vector/nested.ts
index 1102fe8..fe9f7e9 100644
--- a/js/src/vector/nested.ts
+++ b/js/src/vector/nested.ts
@@ -76,31 +76,35 @@ export class UnionView<T extends (DenseUnion | SparseUnion) 
= SparseUnion> exten
     public typeIds: Int8Array;
     // @ts-ignore
     public valueOffsets?: Int32Array;
+    // @ts-ignore
+    protected typeIdToChildIndex: { [key: number]: number };
     constructor(data: Data<T>, children?: Vector<any>[]) {
         super(data, children);
         this.length = data.length;
         this.typeIds = data.typeIds;
+        this.typeIdToChildIndex = data.typeIdToChildIndex;
     }
     protected getNested(self: UnionView<T>, index: number): T['TValue'] {
-        return self.getChildValue(self, index, self.typeIds, 
self.valueOffsets);
+        return self.getChildValue(self, index, self.typeIds, 
self.valueOffsets, self.typeIdToChildIndex);
     }
     protected setNested(self: UnionView<T>, index: number, value: 
T['TValue']): void {
-        return self.setChildValue(self, index, value, self.typeIds, 
self.valueOffsets);
+        return self.setChildValue(self, index, value, self.typeIds, 
self.valueOffsets, self.typeIdToChildIndex);
     }
-    protected getChildValue(self: NestedView<T>, index: number, typeIds: 
Int8Array, _valueOffsets?: any): any | null {
-        const child = self.getChildAt(typeIds[index]);
+    protected getChildValue(self: NestedView<T>, index: number, typeIds: 
Int8Array, _valueOffsets: any, typeIdToChildIndex: { [key: number]: number }): 
any | null {
+        const child = self.getChildAt(typeIdToChildIndex[typeIds[index]]);
         return child ? child.get(index) : null;
     }
-    protected setChildValue(self: NestedView<T>, index: number, value: 
T['TValue'], typeIds: Int8Array, _valueOffsets?: any): any | null {
-        const child = self.getChildAt(typeIds[index]);
+    protected setChildValue(self: NestedView<T>, index: number, value: 
T['TValue'], typeIds: Int8Array, _valueOffsets: any, typeIdToChildIndex: { 
[key: number]: number }): any | null {
+        const child = self.getChildAt(typeIdToChildIndex[typeIds[index]]);
         return child ? child.set(index, value) : null;
     }
     public *[Symbol.iterator](): IterableIterator<T['TValue']> {
         const length = this.length;
         const get = this.getChildValue;
+        const { typeIdToChildIndex } = this;
         const { typeIds, valueOffsets } = this;
         for (let index = -1; ++index < length;) {
-            yield get(this, index, typeIds, valueOffsets);
+            yield get(this, index, typeIds, valueOffsets, typeIdToChildIndex);
         }
     }
 }
@@ -112,14 +116,14 @@ export class DenseUnionView extends UnionView<DenseUnion> 
{
         this.valueOffsets = data.valueOffsets;
     }
     protected getNested(self: DenseUnionView, index: number): any | null {
-        return self.getChildValue(self, index, self.typeIds, 
self.valueOffsets);
+        return self.getChildValue(self, index, self.typeIds, 
self.valueOffsets, self.typeIdToChildIndex);
     }
-    protected getChildValue(self: NestedView<DenseUnion>, index: number, 
typeIds: Int8Array, valueOffsets: any): any | null {
-        const child = self.getChildAt(typeIds[index]);
+    protected getChildValue(self: NestedView<DenseUnion>, index: number, 
typeIds: Int8Array, valueOffsets: any, typeIdToChildIndex: { [key: number]: 
number }): any | null {
+        const child = self.getChildAt(typeIdToChildIndex[typeIds[index]]);
         return child ? child.get(valueOffsets[index]) : null;
     }
-    protected setChildValue(self: NestedView<DenseUnion>, index: number, 
value: any, typeIds: Int8Array, valueOffsets?: any): any | null {
-        const child = self.getChildAt(typeIds[index]);
+    protected setChildValue(self: NestedView<DenseUnion>, index: number, 
value: any, typeIds: Int8Array, valueOffsets: any, typeIdToChildIndex: { [key: 
number]: number }): any | null {
+        const child = self.getChildAt(typeIdToChildIndex[typeIds[index]]);
         return child ? child.set(valueOffsets[index], value) : null;
     }
 }

Reply via email to