Open Profpatsch opened 3 years ago
Do you think attaching some examples to the Projection
type would help? The intuition is it's a function on the columns in the table. For example:
fooAndBar :: Projection (MyTable Expr) (Expr Foo, Expr Bar)
fooAndBar MyTable{ foo, bar } = (foo, bar)
(I think that's right)
Do you think attaching some examples to the
Projection
type would help? The intuition is it's a function on the columns in the table. For example:
yes, I think there’s so many type classes that are just there for plumbing and subtyping, having examples of all the instances in the places that matter (e.g. concrete types for Projection) would really help.
But definitely also an example in the tutorial.
fooAndBar :: Projection (MyTable Expr) (Expr Foo, Expr Bar) fooAndBar MyTable{ foo, bar } = (foo, bar)
This definitely doesn’t work for me. First of all, it infers a MyTable Name
and I’m pretty sure it also doesn’t simply allow using the fields in a tuple.
This will need a bunch more documentation, nobody can figure out what
class (Transposes (Context a) (Field a) a (Transpose (Field a) a), Transposes (Context a) (Field a) b (Transpose (Field a) b)) => Projecting a b
means without a few good examples and some semantics.
Staring at the types a bit more, I inferred that I need something from type MyTable (c :: Context) -> ??
??
naively is MyTable (c2 :: Context)
, but I have no idea how that is a projection if I have to give it all fields.
There is some Transformation
and Rep
shenanigans going on, but for the life of me I can’t figure out how that translates to a tuple of fields.
What speaks against just making the type of Projection :: (MyTable Expr -> MyTable (Const Bool))
or something along that spirit, so for every field you can tell whether it should be taken into account by setting the field to Const True
?
In lieu of any documentation, can you share some code you have and what you want? I'm happy to help you out with that just to unblock you!
I fell back to Hasql and wrote this statement:
Hasql.Trans.statement
( translationKeyId,
translationLanguage,
translationTranslation
)
$ do
let sql =
[Embed.embedVerbatimBytes|
INSERT INTO translation_service.translations
(keyid, language, translation)
VALUES ($1, $2, $3)
-- Every key/language combo can just appear once.
-- if there is a conflict, we just override the entry
-- with the new translation.
ON CONFLICT (keyid, language)
DO UPDATE
SET
translation = EXCLUDED.translation
|]
let encoder =
( contrazip3
(Enc.param (Enc.nonNullable Enc.int8))
(Enc.param (Enc.nonNullable Enc.text))
(Enc.param (Enc.nonNullable Enc.text))
)
The code I mocked up with Rel8 (except for the upsert):
data TranslationTable f = TranslationTable
{ -- translationId :: Column f TranslationId,
translationKeyId :: Column f KeyId,
translationLanguage :: Column f DbLanguageTag,
translationTranslation :: Column f DbTranslatedString
}
deriving stock (Generic)
deriving anyclass (Rel8able)
insert $
Insert
{ into = translationSchema,
rows =
( do
pure $
TranslationTable
{ translationKeyId = lit translationKeyId,
translationLanguage = lit (at & addTranslationLanguage),
translationTranslation = lit (at & addTranslationTranslation)
}
),
-- if there is a conflict, we just override the entry
onConflict =
DoUpdate $
let index :: TranslationTable Expr -> TranslationTable Expr = \tt -> tt
in Upsert
-- TODO: can’t get the UPSERT index working,
-- see https://github.com/circuithub/rel8/issues/131
{ index = id, -- \(TranslationTable {translationKeyId, translationLanguage}) -> (translationKeyId, translationLanguage),
set = \_old new -> new,
updateWhere = \_ _ -> lit True
},
returning = pure ()
}
So basically just overwrite the columns with the new set.
Ok, I think something has broken at some point, because what should work no longer does... Sorry you've ran into this - you're not holding it wrong, we just gave you something broken!
The INSERT/UPSERT docs currently don’t describe how to write a
Projection
.Following the type in the reference leads to
where
Transpose
is an associated type of theTable
class, which has over a dozen instances, so it’s very hard to figure out how aProjection
would actually look like in practice.