Question

I have an entity definition that contains a field of type UTCTime.

Foo
    time UTCTime
    ...

I would like to select a range of those entities ordered by time. If two entities have equal time, I don't care which one comes first, I just want the order to be the same every time. The entity key being unique, it seems ordering by the key would be the perfect choice.

Is it possible to execute a query like selectList and order the matched rows by the primary key? Alternatively

  • is it possible to include the primary key in the entity?
  • or, is there any other way to have a definite order of rows?

Of course, I could always just request order by time and then order the returned list by key myself. But that precludes using the SelectOps OffsetBy and LimitTo, because I cannot know beforehand how many entities with equal time there will be.

Was it helpful?

Solution

I' wasn't sure about the SelectOpts only being applicable to entity value, so I checked that in a small snippet of code. Assuming an entity looks like this:

EntityA
    key Text
    time UTCTime
    deriving Show

you can just list SelectOpts you're interested in and get the desirable output.

The sample code looks like this:

main :: IO ()
main = runSqlite ":memory:" $ do
    runMigration migrateAll

    currentTime <- liftIO getCurrentTime

    -- insert some data
    _ <- insert $ EntityA "first" currentTime
    _ <- insert $ EntityA "second" currentTime
    _ <- insert $ EntityA "third" currentTime
    _ <- insert $ EntityA "fourth" currentTime

    currentTime <- liftIO getCurrentTime

    -- insert more data
    _ <- insert $ EntityA "fifth" currentTime
    _ <- insert $ EntityA "sixth" currentTime
    _ <- insert $ EntityA "seventh" currentTime
    _ <- insert $ EntityA "eighth" currentTime

    currentTime <- liftIO getCurrentTime

    -- insert more data
    _ <- insert $ EntityA "this one will be first" currentTime

    sorted <- selectList [] [Desc EntityATime, Asc EntityAId]
    mapM_ (liftIO . print) sorted

and the output is:

Migrating: CREATE TABLE "entity_a"("id" INTEGER PRIMARY KEY,"key" VARCHAR NOT NULL,"time" TIMESTAMP NOT NULL)
Entity {entityKey = Key {unKey = PersistInt64 9}, entityVal = EntityA {entityAKey = "this one will be first", entityATime = 2014-05-07 20:15:35.627561 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 5}, entityVal = EntityA {entityAKey = "fifth", entityATime = 2014-05-07 20:15:35.627026 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 6}, entityVal = EntityA {entityAKey = "sixth", entityATime = 2014-05-07 20:15:35.627026 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 7}, entityVal = EntityA {entityAKey = "seventh", entityATime = 2014-05-07 20:15:35.627026 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 8}, entityVal = EntityA {entityAKey = "eighth", entityATime = 2014-05-07 20:15:35.627026 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 1}, entityVal = EntityA {entityAKey = "first", entityATime = 2014-05-07 20:15:35.626622 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 2}, entityVal = EntityA {entityAKey = "second", entityATime = 2014-05-07 20:15:35.626622 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 3}, entityVal = EntityA {entityAKey = "third", entityATime = 2014-05-07 20:15:35.626622 UTC}}
Entity {entityKey = Key {unKey = PersistInt64 4}, entityVal = EntityA {entityAKey = "fourth", entityATime = 2014-05-07 20:15:35.626622 UTC}}

I can publish the sample project (it's on fpcomplete.com) if you're interested, but I guess this illustrates it well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top