{"action":"created","comment":{"url":"https://api.github.com/repos/apache/spark/pulls/comments/43963399","id":43963399,"diff_hunk":"@@ -70,43 +76,258 @@ class SimpleTextHadoopFsRelationSuite extends HadoopFsRelationTest {\n     }\n   }\n \n-  private val writer = testDF.write.option(\"dataSchema\", dataSchema.json).format(dataSourceName)\n-  private val reader = sqlContext.read.option(\"dataSchema\", dataSchema.json).format(dataSourceName)\n-\n-  test(\"unhandledFilters\") {\n-    withTempPath { dir =>\n-\n-      val path = dir.getCanonicalPath\n-      writer.save(s\"$path/p=0\")\n-      writer.save(s\"$path/p=1\")\n-\n-      val isOdd = udf((_: Int) % 2 == 1)\n-      val df = reader.load(path)\n-        .filter(\n-          // This filter is inconvertible\n-          isOdd('a) &&\n-            // This filter is convertible but unhandled\n-            'a > 1 &&\n-            // This filter is convertible and handled\n-            'b > \"val_1\" &&\n-            // This filter references a partiiton column, won't be pushed down\n-            'p === 1\n-        ).select('a, 'p)\n-      val rawScan = df.queryExecution.executedPlan collect {\n+  private var tempPath: File = _\n+\n+  private var partitionedDF: DataFrame = _\n+\n+  private val partitionedDataSchema: StructType = StructType('a.int :: 'b.int :: 'c.string :: Nil)\n+\n+  protected override def beforeAll(): Unit = {\n+    this.tempPath = Utils.createTempDir()\n+\n+    val df = sqlContext.range(10).select(\n+      'id cast IntegerType as 'a,\n+      ('id cast IntegerType) * 2 as 'b,\n+      concat(lit(\"val_\"), 'id) as 'c\n+    )\n+\n+    partitionedWriter(df).save(s\"${tempPath.getCanonicalPath}/p=0\")\n+    partitionedWriter(df).save(s\"${tempPath.getCanonicalPath}/p=1\")\n+\n+    partitionedDF = partitionedReader.load(tempPath.getCanonicalPath)\n+  }\n+\n+  override protected def afterAll(): Unit = {\n+    Utils.deleteRecursively(tempPath)\n+  }\n+\n+  private def partitionedWriter(df: DataFrame) =\n+    df.write.option(\"dataSchema\", partitionedDataSchema.json).format(dataSourceName)\n+\n+  private def partitionedReader =\n+    sqlContext.read.option(\"dataSchema\", partitionedDataSchema.json).format(dataSourceName)\n+\n+  /**\n+   * Constructs test cases that test column pruning and filter push-down.\n+   *\n+   * @param projections Projection list of the query\n+   * @param filter Filter condition of the query\n+   * @param requiredColumns Expected names of required columns\n+   * @param pushedFilters Expected data source [[Filter]]s that are pushed down\n+   * @param inconvertibleFilters Expected Catalyst filter [[Expression]]s that cannot be converted\n+   *        to data source [[Filter]]s\n+   * @param unhandledFilters Expected Catalyst flter [[Expression]]s that can be converted to data\n+   *        source [[Filter]]s but cannot be handled by the data source relation\n+   * @param partitioningFilters Expected Catalyst filter [[Expression]]s that reference partition\n+   *        columns\n+   * @param expectedRawScanAnswer Expected query result of the raw table scan returned by the data\n+   *        source relation\n+   * @param expectedAnswer Expected query result of the full query\n+   */\n+  def testPruningAndFiltering(\n+      projections: Seq[Column],\n+      filter: Column,\n+      requiredColumns: Seq[String],\n+      pushedFilters: Seq[Filter],\n+      inconvertibleFilters: Seq[Column],\n+      unhandledFilters: Seq[Column],\n+      partitioningFilters: Seq[Column])(\n+      expectedRawScanAnswer: => Seq[Row])(\n+      expectedAnswer: => Seq[Row]): Unit = {\n+    test(s\"pruning and filtering: df.select(${projections.mkString(\", \")}).where($filter)\") {\n+      val df = partitionedDF.where(filter).select(projections: _*)\n+      val queryExecution = df.queryExecution\n+      val executedPlan = queryExecution.executedPlan\n+\n+      val rawScan = executedPlan.collect {\n         case p: PhysicalRDD => p\n       } match {\n-        case Seq(p) => p\n+        case Seq(scan) => scan\n+        case _ => fail(s\"More than one PhysicalRDD found\\n$queryExecution\")\n       }\n \n-      val outputSchema = new StructType().add(\"a\", IntegerType).add(\"p\", IntegerType)\n+      markup(\"Checking raw scan answer\")\n+      checkAnswer(\n+        DataFrame(sqlContext, LogicalRDD(rawScan.output, rawScan.rdd)(sqlContext)),\n+        expectedRawScanAnswer)\n+\n+      markup(\"Checking full query answer\")\n+      checkAnswer(df, expectedAnswer)\n+\n+      markup(\"Checking required columns\")\n+      assert(requiredColumns === SimpleTextRelation.requiredColumns)\n \n-      assertResult(Set((2, 1), (3, 1))) {\n-        rawScan.execute().collect()\n-          .map { CatalystTypeConverters.convertToScala(_, outputSchema) }\n-          .map { case Row(a, p) => (a, p) }.toSet\n+      val nonPushedFilters = {\n+        val boundFilters = executedPlan.collect {\n+          case f: execution.Filter => f\n+        } match {\n+          case Nil => Nil\n+          case Seq(f) => splitConjunctivePredicates(f.condition)\n+          case _ => fail(s\"More than one PhysicalRDD found\\n$queryExecution\")\n+        }\n+\n+        boundFilters.map {\n+          _.transform { case a: AttributeReference => UnresolvedAttribute(a.name) }\n+        }.toSet\n       }\n \n-      checkAnswer(df, Row(3, 1))\n+      markup(\"Checking pushed filters\")\n+      assert(SimpleTextRelation.pushedFilters === pushedFilters.toSet)\n+\n+      val expectedInconvertibleFilters = inconvertibleFilters.map(_.expr).toSet\n+      val expectedUnhandledFilters = unhandledFilters.map(_.expr).toSet\n+      val expectedPartitioningFilters = partitioningFilters.map(_.expr).toSet\n+\n+      markup(\"Checking unhandled, inconvertible, and partitioning filters\")\n+      assert(expectedInconvertibleFilters ++ expectedUnhandledFilters === nonPushedFilters)\n+      assert(expectedPartitioningFilters.intersect(nonPushedFilters).isEmpty)\n     }\n   }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('*),\n+    filter = 'p > 0,\n+    requiredColumns = Seq(\"a\", \"b\", \"c\"),\n+    pushedFilters = Nil,\n+    inconvertibleFilters = Nil,\n+    unhandledFilters = Nil,\n+    partitioningFilters = Nil\n+  ) {\n+    Seq(\n+      Row(0, 0, \"val_0\", 1),\n+      Row(1, 2, \"val_1\", 1),\n+      Row(2, 4, \"val_2\", 1),\n+      Row(3, 6, \"val_3\", 1),\n+      Row(4, 8, \"val_4\", 1),\n+      Row(5, 10, \"val_5\", 1),\n+      Row(6, 12, \"val_6\", 1),\n+      Row(7, 14, \"val_7\", 1),\n+      Row(8, 16, \"val_8\", 1),\n+      Row(9, 18, \"val_9\", 1))\n+  } {\n+    Seq(\n+      Row(0, 0, \"val_0\", 1),\n+      Row(1, 2, \"val_1\", 1),\n+      Row(2, 4, \"val_2\", 1),\n+      Row(3, 6, \"val_3\", 1),\n+      Row(4, 8, \"val_4\", 1),\n+      Row(5, 10, \"val_5\", 1),\n+      Row(6, 12, \"val_6\", 1),\n+      Row(7, 14, \"val_7\", 1),\n+      Row(8, 16, \"val_8\", 1),\n+      Row(9, 18, \"val_9\", 1))\n+  }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('c, 'p),\n+    filter = 'a < 3 && 'p > 0,\n+    requiredColumns = Seq(\"c\", \"a\"),\n+    pushedFilters = Nil,\n+    inconvertibleFilters = Nil,\n+    unhandledFilters = Seq('a < 3),\n+    partitioningFilters = Nil\n+  ) {\n+    Seq(\n+      Row(\"val_0\", 1, 0),\n+      Row(\"val_1\", 1, 1),\n+      Row(\"val_2\", 1, 2),\n+      Row(\"val_3\", 1, 3),\n+      Row(\"val_4\", 1, 4),\n+      Row(\"val_5\", 1, 5),\n+      Row(\"val_6\", 1, 6),\n+      Row(\"val_7\", 1, 7),\n+      Row(\"val_8\", 1, 8),\n+      Row(\"val_9\", 1, 9))\n+  } {\n+    Seq(\n+      Row(\"val_0\", 1),\n+      Row(\"val_1\", 1),\n+      Row(\"val_2\", 1))\n+  }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('*),\n+    filter = 'a > 8,\n+    requiredColumns = Seq(\"a\", \"b\", \"c\"),\n+    pushedFilters = Seq(GreaterThan(\"a\", 8)),\n+    inconvertibleFilters = Nil,\n+    unhandledFilters = Nil,\n+    partitioningFilters = Nil\n+  ) {\n+    Seq(\n+      Row(9, 18, \"val_9\", 0),\n+      Row(9, 18, \"val_9\", 1))\n+  } {\n+    Seq(\n+      Row(9, 18, \"val_9\", 0),\n+      Row(9, 18, \"val_9\", 1))\n+  }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('b, 'p),\n+    filter = 'a > 8,\n+    requiredColumns = Seq(\"b\"),\n+    pushedFilters = Seq(GreaterThan(\"a\", 8)),\n+    inconvertibleFilters = Nil,\n+    unhandledFilters = Nil,\n+    partitioningFilters = Nil\n+  ) {\n+    Seq(\n+      Row(18, 0),\n+      Row(18, 1))\n+  } {\n+    Seq(\n+      Row(18, 0),\n+      Row(18, 1))\n+  }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('b, 'p),\n+    filter = 'a > 8 && 'p > 0,\n+    requiredColumns = Seq(\"b\"),\n+    pushedFilters = Seq(GreaterThan(\"a\", 8)),\n+    inconvertibleFilters = Nil,\n+    unhandledFilters = Nil,\n+    partitioningFilters = Seq('p > 0)\n+  ) {\n+    Seq(\n+      Row(18, 1))\n+  } {\n+    Seq(\n+      Row(18, 1))\n+  }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('b, 'p),\n+    filter = 'c > \"val_7\" && 'b < 18 && 'p > 0,\n+    requiredColumns = Seq(\"b\"),\n+    pushedFilters = Seq(GreaterThan(\"c\", \"val_7\")),\n+    inconvertibleFilters = Nil,\n+    unhandledFilters = Seq('b < 18),\n+    partitioningFilters = Seq('p > 0)\n+  ) {\n+    Seq(\n+      Row(16, 1),\n+      Row(18, 1))\n+  } {\n+    Seq(\n+      Row(16, 1))\n+  }\n+\n+  testPruningAndFiltering(\n+    projections = Seq('b, 'p),\n+    filter = 'a % 2 === 0 && 'c > \"val_7\" && 'b < 18 && 'p > 0,","path":"sql/hive/src/test/scala/org/apache/spark/sql/sources/SimpleTextHadoopFsRelationSuite.scala","position":300,"original_position":300,"commit_id":"b0aab1518f11e58173ef0db04e1d99d8f621ba60","original_commit_id":"b0aab1518f11e58173ef0db04e1d99d8f621ba60","user":{"login":"liancheng","id":230655,"avatar_url":"https://avatars.githubusercontent.com/u/230655?v=3","gravatar_id":"","url":"https://api.github.com/users/liancheng","html_url":"https://github.com/liancheng","followers_url":"https://api.github.com/users/liancheng/followers","following_url":"https://api.github.com/users/liancheng/following{/other_user}","gists_url":"https://api.github.com/users/liancheng/gists{/gist_id}","starred_url":"https://api.github.com/users/liancheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liancheng/subscriptions","organizations_url":"https://api.github.com/users/liancheng/orgs","repos_url":"https://api.github.com/users/liancheng/repos","events_url":"https://api.github.com/users/liancheng/events{/privacy}","received_events_url":"https://api.github.com/users/liancheng/received_events","type":"User","site_admin":false},"body":"1. Partitioning filters don't participate filter push-down, they are handled separately in `DataSourceStrategy`\r\n2. Catalyst filter `Expression`s that cannot be converted to data source `Filter`s are not pushed down (e.g. UDF and filters referencing multiple columns).\r\n3. Catalyst filter `Expression`s that can be converted to data source `Filter`s but cannot be handled by the underlying data source are not pushed down (e.g. returned from `BaseRelation.unhandledFilters()`).\r\n\r\nAdding the above comments to the test.","created_at":"2015-11-05T00:43:38Z","updated_at":"2015-11-05T00:43:38Z","html_url":"https://github.com/apache/spark/pull/9468#discussion_r43963399","pull_request_url":"https://api.github.com/repos/apache/spark/pulls/9468","_links":{"self":{"href":"https://api.github.com/repos/apache/spark/pulls/comments/43963399"},"html":{"href":"https://github.com/apache/spark/pull/9468#discussion_r43963399"},"pull_request":{"href":"https://api.github.com/repos/apache/spark/pulls/9468"}}},"pull_request":{"url":"https://api.github.com/repos/apache/spark/pulls/9468","id":49693475,"html_url":"https://github.com/apache/spark/pull/9468","diff_url":"https://github.com/apache/spark/pull/9468.diff","patch_url":"https://github.com/apache/spark/pull/9468.patch","issue_url":"https://api.github.com/repos/apache/spark/issues/9468","number":9468,"state":"open","locked":false,"title":"[SPARK-10978] [SQL] [FOLLOW-UP] More comprehensive tests for PR #9399","user":{"login":"liancheng","id":230655,"avatar_url":"https://avatars.githubusercontent.com/u/230655?v=3","gravatar_id":"","url":"https://api.github.com/users/liancheng","html_url":"https://github.com/liancheng","followers_url":"https://api.github.com/users/liancheng/followers","following_url":"https://api.github.com/users/liancheng/following{/other_user}","gists_url":"https://api.github.com/users/liancheng/gists{/gist_id}","starred_url":"https://api.github.com/users/liancheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liancheng/subscriptions","organizations_url":"https://api.github.com/users/liancheng/orgs","repos_url":"https://api.github.com/users/liancheng/repos","events_url":"https://api.github.com/users/liancheng/events{/privacy}","received_events_url":"https://api.github.com/users/liancheng/received_events","type":"User","site_admin":false},"body":"This PR adds test cases that test various column pruning and filter push-down cases.","created_at":"2015-11-04T14:20:13Z","updated_at":"2015-11-05T00:43:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"97ff972f1322f365b155c10bdb43b5a8d3c04545","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/spark/pulls/9468/commits","review_comments_url":"https://api.github.com/repos/apache/spark/pulls/9468/comments","review_comment_url":"https://api.github.com/repos/apache/spark/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/spark/issues/9468/comments","statuses_url":"https://api.github.com/repos/apache/spark/statuses/b0aab1518f11e58173ef0db04e1d99d8f621ba60","head":{"label":"liancheng:spark-10978.follow-up","ref":"spark-10978.follow-up","sha":"b0aab1518f11e58173ef0db04e1d99d8f621ba60","user":{"login":"liancheng","id":230655,"avatar_url":"https://avatars.githubusercontent.com/u/230655?v=3","gravatar_id":"","url":"https://api.github.com/users/liancheng","html_url":"https://github.com/liancheng","followers_url":"https://api.github.com/users/liancheng/followers","following_url":"https://api.github.com/users/liancheng/following{/other_user}","gists_url":"https://api.github.com/users/liancheng/gists{/gist_id}","starred_url":"https://api.github.com/users/liancheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liancheng/subscriptions","organizations_url":"https://api.github.com/users/liancheng/orgs","repos_url":"https://api.github.com/users/liancheng/repos","events_url":"https://api.github.com/users/liancheng/events{/privacy}","received_events_url":"https://api.github.com/users/liancheng/received_events","type":"User","site_admin":false},"repo":{"id":17232535,"name":"spark","full_name":"liancheng/spark","owner":{"login":"liancheng","id":230655,"avatar_url":"https://avatars.githubusercontent.com/u/230655?v=3","gravatar_id":"","url":"https://api.github.com/users/liancheng","html_url":"https://github.com/liancheng","followers_url":"https://api.github.com/users/liancheng/followers","following_url":"https://api.github.com/users/liancheng/following{/other_user}","gists_url":"https://api.github.com/users/liancheng/gists{/gist_id}","starred_url":"https://api.github.com/users/liancheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liancheng/subscriptions","organizations_url":"https://api.github.com/users/liancheng/orgs","repos_url":"https://api.github.com/users/liancheng/repos","events_url":"https://api.github.com/users/liancheng/events{/privacy}","received_events_url":"https://api.github.com/users/liancheng/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/liancheng/spark","description":"Mirror of Apache Spark","fork":true,"url":"https://api.github.com/repos/liancheng/spark","forks_url":"https://api.github.com/repos/liancheng/spark/forks","keys_url":"https://api.github.com/repos/liancheng/spark/keys{/key_id}","collaborators_url":"https://api.github.com/repos/liancheng/spark/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/liancheng/spark/teams","hooks_url":"https://api.github.com/repos/liancheng/spark/hooks","issue_events_url":"https://api.github.com/repos/liancheng/spark/issues/events{/number}","events_url":"https://api.github.com/repos/liancheng/spark/events","assignees_url":"https://api.github.com/repos/liancheng/spark/assignees{/user}","branches_url":"https://api.github.com/repos/liancheng/spark/branches{/branch}","tags_url":"https://api.github.com/repos/liancheng/spark/tags","blobs_url":"https://api.github.com/repos/liancheng/spark/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/liancheng/spark/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/liancheng/spark/git/refs{/sha}","trees_url":"https://api.github.com/repos/liancheng/spark/git/trees{/sha}","statuses_url":"https://api.github.com/repos/liancheng/spark/statuses/{sha}","languages_url":"https://api.github.com/repos/liancheng/spark/languages","stargazers_url":"https://api.github.com/repos/liancheng/spark/stargazers","contributors_url":"https://api.github.com/repos/liancheng/spark/contributors","subscribers_url":"https://api.github.com/repos/liancheng/spark/subscribers","subscription_url":"https://api.github.com/repos/liancheng/spark/subscription","commits_url":"https://api.github.com/repos/liancheng/spark/commits{/sha}","git_commits_url":"https://api.github.com/repos/liancheng/spark/git/commits{/sha}","comments_url":"https://api.github.com/repos/liancheng/spark/comments{/number}","issue_comment_url":"https://api.github.com/repos/liancheng/spark/issues/comments{/number}","contents_url":"https://api.github.com/repos/liancheng/spark/contents/{+path}","compare_url":"https://api.github.com/repos/liancheng/spark/compare/{base}...{head}","merges_url":"https://api.github.com/repos/liancheng/spark/merges","archive_url":"https://api.github.com/repos/liancheng/spark/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/liancheng/spark/downloads","issues_url":"https://api.github.com/repos/liancheng/spark/issues{/number}","pulls_url":"https://api.github.com/repos/liancheng/spark/pulls{/number}","milestones_url":"https://api.github.com/repos/liancheng/spark/milestones{/number}","notifications_url":"https://api.github.com/repos/liancheng/spark/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/liancheng/spark/labels{/name}","releases_url":"https://api.github.com/repos/liancheng/spark/releases{/id}","created_at":"2014-02-27T01:39:03Z","updated_at":"2015-03-31T08:56:24Z","pushed_at":"2015-11-04T14:26:18Z","git_url":"git://github.com/liancheng/spark.git","ssh_url":"git@github.com:liancheng/spark.git","clone_url":"https://github.com/liancheng/spark.git","svn_url":"https://github.com/liancheng/spark","homepage":null,"size":125408,"stargazers_count":1,"watchers_count":1,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"c09e5139874fb3626e005c8240cca5308b902ef3","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":17165658,"name":"spark","full_name":"apache/spark","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/spark","description":"Mirror of Apache Spark","fork":false,"url":"https://api.github.com/repos/apache/spark","forks_url":"https://api.github.com/repos/apache/spark/forks","keys_url":"https://api.github.com/repos/apache/spark/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/spark/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/spark/teams","hooks_url":"https://api.github.com/repos/apache/spark/hooks","issue_events_url":"https://api.github.com/repos/apache/spark/issues/events{/number}","events_url":"https://api.github.com/repos/apache/spark/events","assignees_url":"https://api.github.com/repos/apache/spark/assignees{/user}","branches_url":"https://api.github.com/repos/apache/spark/branches{/branch}","tags_url":"https://api.github.com/repos/apache/spark/tags","blobs_url":"https://api.github.com/repos/apache/spark/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/spark/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/spark/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/spark/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/spark/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/spark/languages","stargazers_url":"https://api.github.com/repos/apache/spark/stargazers","contributors_url":"https://api.github.com/repos/apache/spark/contributors","subscribers_url":"https://api.github.com/repos/apache/spark/subscribers","subscription_url":"https://api.github.com/repos/apache/spark/subscription","commits_url":"https://api.github.com/repos/apache/spark/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/spark/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/spark/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/spark/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/spark/contents/{+path}","compare_url":"https://api.github.com/repos/apache/spark/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/spark/merges","archive_url":"https://api.github.com/repos/apache/spark/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/spark/downloads","issues_url":"https://api.github.com/repos/apache/spark/issues{/number}","pulls_url":"https://api.github.com/repos/apache/spark/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/spark/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/spark/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/spark/labels{/name}","releases_url":"https://api.github.com/repos/apache/spark/releases{/id}","created_at":"2014-02-25T08:00:08Z","updated_at":"2015-11-04T23:29:22Z","pushed_at":"2015-11-05T00:35:23Z","git_url":"git://github.com/apache/spark.git","ssh_url":"git@github.com:apache/spark.git","clone_url":"https://github.com/apache/spark.git","svn_url":"https://github.com/apache/spark","homepage":null,"size":1653686,"stargazers_count":6013,"watchers_count":6013,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":5603,"mirror_url":"git://git.apache.org/spark.git","open_issues_count":375,"forks":5603,"open_issues":375,"watchers":6013,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/spark/pulls/9468"},"html":{"href":"https://github.com/apache/spark/pull/9468"},"issue":{"href":"https://api.github.com/repos/apache/spark/issues/9468"},"comments":{"href":"https://api.github.com/repos/apache/spark/issues/9468/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/spark/pulls/9468/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/spark/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/spark/pulls/9468/commits"},"statuses":{"href":"https://api.github.com/repos/apache/spark/statuses/b0aab1518f11e58173ef0db04e1d99d8f621ba60"}}}}