17
17
18
18
package org .apache .spark .sql
19
19
20
+ import scala .util .hashing .MurmurHash3
21
+
20
22
import org .apache .spark .sql .catalyst .expressions .GenericRow
21
23
22
24
@@ -32,7 +34,7 @@ object Row {
32
34
* }
33
35
* }}}
34
36
*/
35
- def unapplySeq (row : Row ): Some [Seq [Any ]] = Some (row)
37
+ def unapplySeq (row : Row ): Some [Seq [Any ]] = Some (row.toSeq )
36
38
37
39
/**
38
40
* This method can be used to construct a [[Row ]] with the given values.
@@ -43,6 +45,16 @@ object Row {
43
45
* This method can be used to construct a [[Row ]] from a [[Seq ]] of values.
44
46
*/
45
47
def fromSeq (values : Seq [Any ]): Row = new GenericRow (values.toArray)
48
+
49
+ def fromTuple (tuple : Product ): Row = fromSeq(tuple.productIterator.toSeq)
50
+
51
+ /**
52
+ * Merge multiple rows into a single row, one after another.
53
+ */
54
+ def merge (rows : Row * ): Row = {
55
+ // TODO: Improve the performance of this if used in performance critical part.
56
+ new GenericRow (rows.flatMap(_.toSeq).toArray)
57
+ }
46
58
}
47
59
48
60
@@ -103,7 +115,13 @@ object Row {
103
115
*
104
116
* @group row
105
117
*/
106
- trait Row extends Seq [Any ] with Serializable {
118
+ trait Row extends Serializable {
119
+ /** Number of elements in the Row. */
120
+ def size : Int = length
121
+
122
+ /** Number of elements in the Row. */
123
+ def length : Int
124
+
107
125
/**
108
126
* Returns the value at position i. If the value is null, null is returned. The following
109
127
* is a mapping between Spark SQL types and return types:
@@ -291,12 +309,64 @@ trait Row extends Seq[Any] with Serializable {
291
309
292
310
/** Returns true if there are any NULL values in this row. */
293
311
def anyNull : Boolean = {
294
- val l = length
312
+ val l = size
295
313
var i = 0
296
314
while (i < l) {
297
315
if (isNullAt(i)) { return true }
298
316
i += 1
299
317
}
300
318
false
301
319
}
320
+
321
+ override def equals (that : Any ): Boolean = that match {
322
+ case null => false
323
+ case that : Row =>
324
+ if (this .length != that.length) {
325
+ return false
326
+ }
327
+ var i = 0
328
+ val len = this .length
329
+ while (i < len) {
330
+ if (apply(i) != that.apply(i)) {
331
+ return false
332
+ }
333
+ i += 1
334
+ }
335
+ true
336
+ case _ => false
337
+ }
338
+
339
+ override def hashCode : Int = {
340
+ // Using Scala's Seq hash code implementation.
341
+ var n = 0
342
+ var h = MurmurHash3 .seqSeed
343
+ val len = length
344
+ while (n < len) {
345
+ h = MurmurHash3 .mix(h, apply(n).## )
346
+ n += 1
347
+ }
348
+ MurmurHash3 .finalizeHash(h, n)
349
+ }
350
+
351
+ /* ---------------------- utility methods for Scala ---------------------- */
352
+
353
+ /**
354
+ * Return a Scala Seq representing the row. ELements are placed in the same order in the Seq.
355
+ */
356
+ def toSeq : Seq [Any ]
357
+
358
+ /** Displays all elements of this sequence in a string (without a separator). */
359
+ def mkString : String = toSeq.mkString
360
+
361
+ /** Displays all elements of this sequence in a string using a separator string. */
362
+ def mkString (sep : String ): String = toSeq.mkString(sep)
363
+
364
+ /**
365
+ * Displays all elements of this traversable or iterator in a string using
366
+ * start, end, and separator strings.
367
+ */
368
+ def mkString (start : String , sep : String , end : String ): String = toSeq.mkString(start, sep, end)
369
+
370
+ /** Selects the first element of this row. */
371
+ def head : Any = apply(0 )
302
372
}
0 commit comments