You are viewing a plain text version of this content. The canonical link for it is here.
Posted to reviews@spark.apache.org by viirya <gi...@git.apache.org> on 2017/09/17 14:08:27 UTC

[GitHub] spark pull request #16578: [SPARK-4502][SQL] Parquet nested column pruning

Github user viirya commented on a diff in the pull request:

    https://github.com/apache/spark/pull/16578#discussion_r139311391
  
    --- Diff: sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/planning/SelectedField.scala ---
    @@ -0,0 +1,144 @@
    +/*
    + * 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.
    + */
    +
    +package org.apache.spark.sql.catalyst.planning
    +
    +import org.apache.spark.sql.catalyst.expressions._
    +import org.apache.spark.sql.types._
    +
    +/**
    + * A Scala extractor that builds a [[org.apache.spark.sql.types.StructField]] from a Catalyst
    + * complex type extractor. For example, consider a relation with the following schema:
    + *
    + *   {{{
    + *   root
    + *    |-- name: struct (nullable = true)
    + *    |    |-- first: string (nullable = true)
    + *    |    |-- last: string (nullable = true)
    + *    }}}
    + *
    + * Further, suppose we take the select expression `name.first`. This will parse into an
    + * `Alias(child, "first")`. Ignoring the alias, `child` matches the following pattern:
    + *
    + *   {{{
    + *   GetStructFieldObject(
    + *     AttributeReference("name", StructType(_), _, _),
    + *     StructField("first", StringType, _, _))
    + *   }}}
    + *
    + * [[SelectedField]] converts that expression into
    + *
    + *   {{{
    + *   StructField("name", StructType(Array(StructField("first", StringType))))
    + *   }}}
    + *
    + * by mapping each complex type extractor to a [[org.apache.spark.sql.types.StructField]] with the
    + * same name as its child (or "parent" going right to left in the select expression) and a data
    + * type appropriate to the complex type extractor. In our example, the name of the child expression
    + * is "name" and its data type is a [[org.apache.spark.sql.types.StructType]] with a single string
    + * field named "first".
    + *
    + * @param expr the top-level complex type extractor
    + */
    +object SelectedField {
    +  def unapply(expr: Expression): Option[StructField] = {
    +    // If this expression is an alias, work on its child instead
    +    val unaliased = expr match {
    +      case Alias(child, _) => child
    +      case expr => expr
    +    }
    +    selectField(unaliased, None)
    +  }
    +
    +  private def selectField(expr: Expression, fieldOpt: Option[StructField]): Option[StructField] = {
    +    expr match {
    +      // No children. Returns a StructField with the attribute name or None if fieldOpt is None.
    +      case AttributeReference(name, dataType, nullable, metadata) =>
    +        fieldOpt.map(field =>
    +          StructField(name, wrapStructType(dataType, field), nullable, metadata))
    +      // Handles case "expr0.field[n]", where "expr0" is of struct type and "expr0.field" is of
    +      // array type.
    +      case GetArrayItem(x @ GetStructFieldObject(child, field @ StructField(name,
    +          dataType, nullable, metadata)), _) =>
    +        val childField = fieldOpt.map(field => StructField(name,
    +          wrapStructType(dataType, field), nullable, metadata)).getOrElse(field)
    +        selectField(child, Some(childField))
    +      // Handles case "expr0.field[n]", where "expr0.field" is of array type.
    +      case GetArrayItem(child, _) =>
    +        selectField(child, fieldOpt)
    +      // Handles case "expr0.field.subfield", where "expr0" and "expr0.field" are of array type.
    +      case GetArrayStructFields(child: GetArrayStructFields,
    +          field @ StructField(name, dataType, nullable, metadata), _, _, _) =>
    +        val childField = fieldOpt.map(field => StructField(name,
    +            wrapStructType(dataType, field),
    +            nullable, metadata)).getOrElse(field)
    +        selectField(child, Some(childField))
    +      // Handles case "expr0.field", where "expr0" is of array type.
    +      case GetArrayStructFields(child,
    +          field @ StructField(name, dataType, nullable, metadata), _, _, containsNull) =>
    +        val childField =
    +          fieldOpt.map(field => StructField(name,
    +            wrapStructType(dataType, field),
    +            nullable, metadata)).getOrElse(field)
    +        selectField(child, Some(childField)).map {
    --- End diff --
    
    line 97-107 can be simplified as `selectField(child, Some(childField))`, if line 121-126 becomes:
    
            case GetStructFieldObject(child,
        -    field @ StructField(name, _, nullable, metadata)) =>
        +    field @ StructField(name, dataType, nullable, metadata)) =>
             val childField = fieldOpt.map(field => StructField(name,
        -      StructType(Array(field)),
        +      wrapStructType(dataType, field),
               nullable, metadata)).getOrElse(field)
             selectField(child, Some(childField))
    
    All tests in `SelectedFieldSuite` are passed.


---

---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org