korma / Korma

Tasty SQL for Clojure.
http://sqlkorma.com
1.48k stars 222 forks source link

unable to count #266

Closed Rugal closed 9 years ago

Rugal commented 9 years ago

Hello: I am new to korma hence have a question maybe very easy. Here is my entity:

(declare restaurant menu)
(defentity restaurant
  (pk :rid)
  (entity-fields :rid :address :name :phone)
  (has-many menu {:fk :rid})
  )
(defentity menu
  (pk :mid)
  (entity-fields :mid :name :price :rid)
  (belongs-to restaurant {:fk :rid})
  )

I try to execute select count(*) from restaurant in korma like:

(defn count     ""   []
  (korma/select
    restaurant
    (korma/aggregate (count :*) :cnt)
    )

)

But in generate the SQL as below and also give me the error:

user=> (count)
Failure to execute query with SQL:
SELECT "restaurant"."rid", "restaurant"."address", "restaurant"."name", "restaurant"."phone", count(1) total FROM "restaurant"  ::  []
PSQLException:
 Message: ERROR: column "restaurant.rid" must appear in the GROUP BY clause or be used in an aggregate function
  Position: 8
 SQLState: 42803
 Error Code: 0

Which automatically includes all fields in my entity. I also tried the

(defn count     ""   []
  (korma/select
    restaurant
    (korma/fields (raw "count(*) total"))
    )
)

But still not work, it still generate all fields in projection list. Could anyone help me?

immoh commented 9 years ago

defentity defines a base query and relations for the table. When querying using the entity, you can add things, such as additional fields and where conditions, and define which relations to fetch using with. Unfortunately it doesn't work well together with aggregate since the entity fields will be always included in the query. Simple use table name for the aggregate query:

(sql-only (select :restaurant (aggregate (count :*) :cnt)))
=> "SELECT COUNT(\"restaurant\".*) AS \"cnt\" FROM \"restaurant\""
Rugal commented 9 years ago

Thanks for the reply, I also found in other places where I need only limited number of fields, korma will put all the default fields as well as the (fields ) content.
Thus I think the best strategy maybe is to manually specify fields in (select) when on use rather than set them in defentity.

Hope some version in the future could address this cumbersome thing in a more flexible way.