@@ -2,7 +2,7 @@ module Yoga.Postgres.Schema where
22
33import Prelude
44
5−import Data.Array (intercalate)
5+import Data.Array (intercalate, length, mapWithIndex)
66
77import Data.Maybe (Maybe)
88import Data.Symbol (class IsSymbol, reflectSymbol)
@@ -139,3 +139,61 @@ instance
139139 let tableName = reflectSymbol (Proxy :: Proxy name)
140140 let columns = renderColumnsRL (Proxy :: Proxy rl)
141141 "CREATE TABLE " <> tableName <> " (" <> intercalate ", " columns <> ")"
142+
143+-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
144+-- INSERT SQL generation
145+-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
146+
147+class IsAutoGenerated a where
148+ isAutoGenerated :: Proxy a -> Boolean
149+
150+instance IsAutoGenerated AutoIncrement where
151+ isAutoGenerated _ = true
152+else instance IsAutoGenerated (Default a) where
153+ isAutoGenerated _ = true
154+else instance (IsAutoGenerated a, IsAutoGenerated b) => IsAutoGenerated (a /\ b) where
155+ isAutoGenerated _ = isAutoGenerated (Proxy :: Proxy a) || isAutoGenerated (Proxy :: Proxy b)
156+else instance IsAutoGenerated a where
157+ isAutoGenerated _ = false
158+
159+class InsertColumnsRL :: RL.RowList Type -> Constraint
160+class InsertColumnsRL rl where
161+ insertColumnsRL :: Proxy rl -> Array String
162+
163+instance InsertColumnsRL RL.Nil where
164+ insertColumnsRL _ = []
165+
166+instance
167+ ( IsSymbol name
168+ , IsAutoGenerated constraints
169+ , InsertColumnsRL tail
170+ ) =>
171+ InsertColumnsRL (RL.Cons name (Column typ constraints) tail) where
172+ insertColumnsRL _ =
173+ let
174+ rest = insertColumnsRL (Proxy :: Proxy tail)
175+ in
176+ if isAutoGenerated (Proxy :: Proxy constraints) then rest
177+ else [ reflectSymbol (Proxy :: Proxy name) ] <> rest
178+
179+class InsertSQLFor a where
180+ insertSQLFor :: String
181+
182+instance
183+ ( IsSymbol name
184+ , RowToList cols rl
185+ , InsertColumnsRL rl
186+ ) =>
187+ InsertSQLFor (Table name cols) where
188+ insertSQLFor = do
189+ let tableName = reflectSymbol (Proxy :: Proxy name)
190+ let cols = insertColumnsRL (Proxy :: Proxy rl)
191+ let placeholders = cols # mapWithIndex \i _ -> "$" <> show (i + 1)
192+ "INSERT INTO " <> tableName
193+ <> " ("
194+ <> intercalate ", " cols
195+ <> ")"
196+ <> " VALUES ("
197+ <> intercalate ", " placeholders
198+ <> ")"
199+ <> " RETURNING *"