khibino / haskell-relational-record

This repository includes a joined query generator based on typefull relational algebra, and mapping tools between SQL values list and Haskell record type.
233 stars 36 forks source link

Mapping of PostgreSQL's type 'real' does not work #76

Open 64pcyk opened 4 years ago

64pcyk commented 4 years ago

Hello, Kei-san! I am trying to use Haskell-Relational-Record with PostgreSQL 12 (psql (12.1 (Debian 12.1-1.pgdg100+1))) and when I defined a table containing simple types (text, integer) - with defineTableFromDB - it's OK. But when I try to do the same for table with SQL type real then I get an error:

/root/xyz/pgsql-poc/hrr/src/Countrylanguage.hs:22:3: error:
    • No instance for (PersistableWidth Float)
        arising from a use of ‘Database.Record.Persistable.genericFieldOffsets’
    • In the first argument of ‘Database.Record.Persistable.getProductConst’, namely
        ‘(Database.Record.Persistable.genericFieldOffsets ::
            Database.Record.Persistable.ProductConst (GHC.Arr.Array Int Int) Countrylanguage)’
      In the expression:
        Database.Record.Persistable.getProductConst
          (Database.Record.Persistable.genericFieldOffsets ::
             Database.Record.Persistable.ProductConst (GHC.Arr.Array Int Int) Countrylanguage)
      In an equation for ‘columnOffsetsCountrylanguage’:
          columnOffsetsCountrylanguage
            = Database.Record.Persistable.getProductConst
                (Database.Record.Persistable.genericFieldOffsets ::
                   Database.Record.Persistable.ProductConst (GHC.Arr.Array Int Int) Countrylanguage)
   |
22 | $(defineTable2
   |   ^^^^^^^^^^^^...

/root/xyz/pgsql-poc/hrr/src/Countrylanguage.hs:22:3: error:
    • No instance for (ToSql Database.HDBC.SqlValue.SqlValue Float)
        arising from a use of ‘Database.Record.ToSql.$dmrecordToSql’
    • In the expression:
        Database.Record.ToSql.$dmrecordToSql
          @(Database.HDBC.SqlValue.SqlValue) @(Countrylanguage)
      In an equation for ‘recordToSql’:
          recordToSql
            = Database.Record.ToSql.$dmrecordToSql
                @(Database.HDBC.SqlValue.SqlValue) @(Countrylanguage)
      In the instance declaration for
        ‘ToSql Database.HDBC.SqlValue.SqlValue Countrylanguage’
   |
22 | $(defineTable2
   |   ^^^^^^^^^^^^...

/root/xyz/pgsql-poc/hrr/src/Countrylanguage.hs:22:3: error:
    • No instance for (FromSql Database.HDBC.SqlValue.SqlValue Float)
        arising from a use of ‘Database.Record.FromSql.$dmrecordFromSql’
    • In the expression:
        Database.Record.FromSql.$dmrecordFromSql
          @(Database.HDBC.SqlValue.SqlValue) @(Countrylanguage)
      In an equation for ‘recordFromSql’:
          recordFromSql
            = Database.Record.FromSql.$dmrecordFromSql
                @(Database.HDBC.SqlValue.SqlValue) @(Countrylanguage)
      In the instance declaration for
        ‘FromSql Database.HDBC.SqlValue.SqlValue Countrylanguage’
   |
22 | $(defineTable2
   |   ^^^^^^^^^^^^...

/root/xyz/pgsql-poc/hrr/src/Countrylanguage.hs:22:3: error:
    • No instance for (PersistableWidth Float)
        arising from a use of ‘Database.Relational.Pi.Unsafe.definePi’
    • In the expression:
        (Database.Relational.Pi.Unsafe.definePi
           $ (columnOffsetsCountrylanguage GHC.Arr.! 3))
      In an equation for ‘Database.Relational.OverloadedProjection.projection’:
          Database.Relational.OverloadedProjection.projection _
            = (Database.Relational.Pi.Unsafe.definePi
                 $ (columnOffsetsCountrylanguage GHC.Arr.! 3))
      In the instance declaration for
        ‘Database.Relational.OverloadedProjection.HasProjection
           "percentage" Countrylanguage Float’
   |
22 | $(defineTable2
   |   ^^^^^^^^^^^^...

This is the code which describes the table:

...
defineTable2 :: String -> String -> [Name] -> Q [Dec]
defineTable2 = defineTableFromDB connectDatabase driverPostgreSQL
...

-- in another module:
...
$(defineTable2
    "public" "countrylanguage"
    [''Show, ''Generic])
...

The table "countrylanguage" is a table from the famous database "world" for PostgreSQL, which looks like:

postgres=# \dt
              List of relations
 Schema |      Name       | Type  |  Owner   
--------+-----------------+-------+----------
 public | city            | table | postgres
 public | country         | table | postgres
 public | countrylanguage | table | postgres

and a specially the table "countrylanguage" looks like:

postgres=# \d countrylanguage
               Table "public.countrylanguage"
   Column    |     Type     | Collation | Nullable | Default 
-------------+--------------+-----------+----------+---------
 countrycode | character(3) |           | not null | 
 language    | text         |           | not null | 
 isofficial  | boolean      |           | not null | 
 percentage  | real         |           | not null | 
Indexes:
    "countrylanguage_pkey" PRIMARY KEY, btree (countrycode, language)
Foreign-key constraints:
    "countrylanguage_countrycode_fkey" FOREIGN KEY (countrycode) REFERENCES country(code)

Is it an error? Or I miss something? How to fix it? I found some examples with the type "Float" for SQLite3, but why it does not work for PostgreSQL, I have not idea.

PS. Very similar code works fine for table "city" which does not contain columns of "real" type.

64pcyk commented 4 years ago

I'll add only that I tried also:

...
defineTable1 :: [(String, TypeQ)] -> String -> String -> [Name] -> Q [Dec]
defineTable1 tmap = defineTableFromDB connectDatabase (driverPostgreSQL { typeMap = tmap })
...

-- in another module
...
$(defineTable1
    [
        ("real", [t|Double|]),
        ("float", [t|Double|]),
        ("double", [t|Double|])
    ]
    "public" "countrylanguage"
    [''Show, ''Generic])
...

but errors are the same (about missing instances for type Float).