1

Here's a subset of my model:

ServerWebsite
    desc Text
    url Text
    text Text
    username Text
    password Password
    serverDatabaseId ServerDatabaseId Maybe
    groupName Text Maybe
    serverId ServerId
    deriving Show Typeable
ServerDatabase
    desc Text
    name Text
    text Text
    username Text
    password Password
    groupName Text Maybe
    serverId ServerId
    deriving Show Typeable

I can't make this query build:

filterServerWebsites :: SqlExpr (Value Text) -> SqlPersistM [Entity ServerWebsite]
filterServerWebsites query = select $ from $ \(w `LeftOuterJoin` db) -> do
    on (w ^. ServerWebsiteServerDatabaseId ==. db ?. ServerDatabaseId)
    where_ ((w ^. ServerWebsiteDesc `like` query)
        ||. (w ^. ServerWebsiteUrl `like` query)
        ||. (w ^. ServerWebsiteText `like` query)
        ||. (db ?. ServerDatabaseDesc `like` just query))
    return w

I don't understand the build errors:

    • Couldn't match expected type ‘SqlQuery a1’
                  with actual type ‘(a0 -> b0) -> a0 -> a0 -> c0’
    • Probable cause: ‘on’ is applied to too few arguments
      In a stmt of a 'do' block:
        on (w ^. ServerWebsiteServerDatabaseId ==. db ?. ServerDatabaseId)

and:

    • Couldn't match expected type ‘b0 -> b0 -> c0’
                  with actual type ‘SqlExpr (Value Bool)’
    • Possible cause: ‘(==.)’ is applied to too many arguments
      In the first argument of ‘on’, namely
        ‘(w ^. ServerWebsiteServerDatabaseId ==. db ?. ServerDatabaseId)’

I don't understand where I'm going wrong?

EDIT I was starting from this code, which does work:

filterServerWebsites :: SqlExpr (Value Text) -> SqlPersistM [Entity ServerWebsite]
filterServerWebsites query = select $ from $ \w -> do
    where_ ((w ^. ServerWebsiteDesc `like` query)
        ||. (w ^. ServerWebsiteUrl `like` query)
        ||. (w ^. ServerWebsiteText `like` query))
    return w
Emmanuel Touzery
  • 9,008
  • 3
  • 65
  • 81
  • Is `ServerDatabaseId` actually `ServerDatabaseServerId` ? – chi Jan 16 '18 at 13:51
  • no, the `Server` table is unrelated. Here we have only `ServerWebsite` and `ServerDatabase`. Trying to query `ServerWebsite` and getting an outer join on `ServerDatabase` through `serverDatabaseId ServerDatabaseId Maybe`. So `ServerDatabaseId` is meant to be the PK of `ServerDatabase`. – Emmanuel Touzery Jan 16 '18 at 13:54
  • Uhm, ok. I'm not an esqueleto expert, but I thought `db ?. ServerDatabaseId` would access a non existing field `id` in `ServerDatabase`. (I might be very wrong on this, though.) – chi Jan 16 '18 at 15:12
  • From my understanding `db` is a `Maybe` entity because it's an outer join, therefore the right table may not have a record. That's the reason I think we need `?.` instead of `^.`. – Emmanuel Touzery Jan 16 '18 at 15:49
  • I'm not concerned about `?.` but about the name `ServerDatabaseId`, since above `ServerDatabase` has no `id` field, only a `serverId` field. – chi Jan 16 '18 at 16:03
  • I think that's correct. The id field is always present in persistent. See `getBlogPostsByAuthors` in https://github.com/bitemyapp/esqueleto/blob/master/examples/Main.hs -- it uses `PersonId` but the model doesn't declare person.id – Emmanuel Touzery Jan 16 '18 at 16:15

1 Answers1

1

Right. So really my own stupidity. I should have made a sample project to reproduce the issue, then I would have spotted the issue.

The issue was that I had at the top of the file...

import Database.Esqueleto hiding (on)
import Data.Function

... because I was using somewhere else in that file on from Data.Function.

I changed that to...

import Database.Esqueleto
import qualified Data.Function as F

And now all works fine...

Emmanuel Touzery
  • 9,008
  • 3
  • 65
  • 81