Skip to content

Error when using subquery containing window function #2281

Closed
@dipth

Description

@dipth

Environment

  • Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
  • Elixir 1.5.1
  • PostgreSQL 9.6.3 on x86_64-apple-darwin16.5.0, compiled by Apple LLVM version 8.1.0 (clang-802.0.42), 64-bit
  • ecto 2.2.6
  • postgrex 0.13.3
  • mac OS X High Sierra 10.13 (17A405)

Current behavior

Given the following module:

defmodule MyApp.BlogPost
  alias MyApp.Repo
  use MyApp.Web, :model

  schema "blog_posts" do
    field :title,         :string
    field :body,          :string
    field :published_at,  Calecto.DateTimeUTC

    timestamps()
  end

  def newest_for_frontpage(limit) do
    sq = from(
      bp in (MyApp.BlogPost),
      select: %{id: bp.id, row_number: fragment("row_number() OVER (PARTITION BY ? ORDER BY ? DESC)", bp.user_id, bp.published_at)}
    )

    from(
      bp in (MyApp.BlogPost),
      join: rn in subquery(sq), on: rn.id == bp.id,
      where: rn.row_number == 1,
      limit: ^limit
    )
  end
end

And the following calling code:

BlogPost.newest_for_frontpage(8)
|> Repo.all

Results in the following error:

    ** (Postgrex.Error) ERROR 42601 (syntax_error): syntax error at or near "."
        (ecto) lib/ecto/adapters/sql.ex:431: Ecto.Adapters.SQL.execute_and_cache/7
        (ecto) lib/ecto/repo/queryable.ex:133: Ecto.Repo.Queryable.execute/5
        (ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4

Expected behavior

Before the error is raised, the following debug output can be seen in the log:

[debug] QUERY ERROR source="blog_posts" db=0.4ms
SELECT b0."id", b0."title", b0."body", b0."visitor_count", b0."comment_count", b0."published", b0."published_at", b0."inserted_at", b0."updated_at", b0."user_id" FROM "blog_posts" AS b0 INNER JOIN (SELECT b0."id" AS "id", row_number() OVER (PARTITION BY b0."user_id" ORDER BY b0."published_at" DESC) AS "row_number" FROM "blog_posts" AS b0) AS s1 ON s1."id" = b0."id" WHERE (s1."row_number" = 1) LIMIT $1 [8]
[info] Sent 500 in 38ms

Running that query (replacing $1 [8] with simply 8) directly in the database, returns a set of records just fine.
The expected behaviour would thus be for Ecto to also return the records instead of raising an error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions