bitemyapp / esqueleto

New home of Esqueleto, please file issues so we can get things caught up!
BSD 3-Clause "New" or "Revised" License
370 stars 107 forks source link

esqueleto-3.5.0.0 generates malformed SQL when notIn is passed an empty list #272

Closed cdparks closed 3 years ago

cdparks commented 3 years ago

An notIn expression using the legacy API:

fetchUsersExcept :: MonadIO m => [Text] -> SqlReadT m [Entity User]
fetchUsersExcept names = select . from $ \users -> do
  where_ $ users ^. UserName `notIn` valList names
  pure users

or the experimental API:

fetchUsersExcept :: MonadIO m => [Text] -> SqlReadT m [Entity User]
fetchUsersExcept names = select $ do
  users <- from $ table @User
  where_ $ users ^. UserName `notIn` valList names
  pure users

will generate a malformed SQL query when passed an empty list:

fetchUsersExcept []

=>

[Debug#SQL]
SELECT "users"."id", "users"."name"
FROM "users"
WHERE "users"."name" NOT IN (); []
esqueleto-bug: SqlError {sqlState = "42601", sqlExecStatus = FatalError, sqlErrorMsg = "syntax error at or near \")\"", sqlErrorDetail = "", sqlErrorHint = ""}

Apparently Postgres (I'm using 10.14) doesn't like x NOT IN (). Sqlite seems to accept this syntax.

It looks to me like esqueleto protects against passing an empty list for in_, but not for notIn. This seems like a behavior change based on this older commit, which used a helper function ifNotEmptyList.

I have a repo demonstrating this, but it's probably easiest to verify this in your own setup.

belevy commented 3 years ago

273 fixes the issue