git.iko.soy/rowtype-yoga/purescript-yoga-postgres
on main help sign in
commitab6e5ecbdbdba639cd57be0c5deb9213cf758994 authorMark <mark.eibes@gmail.com> dateFri 13 Feb 2026, 14:05 (8 months ago) parent9a2f17f
2 files changed+50−5
src/Yoga/Postgres/Schema.purs+39 test/Schema.purs+11−5
src/Yoga/Postgres/Schema.purs+39
@@ -197,3 +197,42 @@ instance
197197 <> intercalate ", " placeholders
198198 <> ")"
199199 <> " RETURNING *"
200+
201+-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
202+-- SELECT SQL generation
203+-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
204+
205+class SelectAllSQLFor a where
206+ selectAllSQLFor :: String
207+
208+instance
209+ ( IsSymbol name
210+ ) =>
211+ SelectAllSQLFor (Table name cols) where
212+ selectAllSQLFor = "SELECT * FROM " <> reflectSymbol (Proxy :: Proxy name)
213+
214+class WhereClauseRL :: RL.RowList Type -> Constraint
215+class WhereClauseRL rl where
216+ whereClauseRL :: Proxy rl -> Int -> Array String
217+
218+instance WhereClauseRL RL.Nil where
219+ whereClauseRL _ _ = []
220+
221+instance (IsSymbol name, WhereClauseRL tail) => WhereClauseRL (RL.Cons name typ tail) where
222+ whereClauseRL _ idx =
223+ [ reflectSymbol (Proxy :: Proxy name) <> " = $" <> show idx ]
224+ <> whereClauseRL (Proxy :: Proxy tail) (idx + 1)
225+
226+class SelectWhereSQLFor a whereRow where
227+ selectWhereSQLFor :: String
228+
229+instance
230+ ( IsSymbol name
231+ , RowToList whereRow whereRL
232+ , WhereClauseRL whereRL
233+ ) =>
234+ SelectWhereSQLFor (Table name cols) whereRow where
235+ selectWhereSQLFor = do
236+ let tableName = reflectSymbol (Proxy :: Proxy name)
237+ let conditions = whereClauseRL (Proxy :: Proxy whereRL) 1
238+ "SELECT * FROM " <> tableName <> " WHERE " <> intercalate " AND " conditions
test/Schema.purs+11−5
@@ -42,11 +42,11 @@ insertSQL = insertSQLFor @UsersTable
4242-- Phase 4: Type-safe SELECT
4343-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4444
45−-- allUsers :: PG.Connection -> Aff (Either String (Array { id :: Int, name :: String, email :: String, age :: Maybe Int }))
46−-- allUsers conn = selectAll @UsersTable conn
45+selectAllSQL :: String
46+selectAllSQL = selectAllSQLFor @UsersTable
4747
48−-- userById :: PG.Connection -> Aff (Either String (Array { id :: Int, name :: String, email :: String, age :: Maybe Int }))
49−-- userById conn = selectWhere @UsersTable { id: 1 } conn
48+selectWhereSQL :: String
49+selectWhereSQL = selectWhereSQLFor @UsersTable @(id :: Int)
5050
5151-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
5252-- Phase 5: Type-level defaults
@@ -97,8 +97,14 @@ spec = do
9797 ddl `shouldSatisfy` contains (Pattern "age INTEGER,")
9898
9999 describe "INSERT SQL" do
100− it "generates INSERT skipping PrimaryKey columns" do
100+ it "generates INSERT skipping AutoIncrement columns" do
101101 insertSQL `shouldSatisfy` contains (Pattern "INSERT INTO users")
102102 insertSQL `shouldSatisfy` contains (Pattern "(age, email, name)")
103103 insertSQL `shouldSatisfy` contains (Pattern "VALUES ($1, $2, $3)")
104104 insertSQL `shouldSatisfy` contains (Pattern "RETURNING *")
105+
106+ describe "SELECT SQL" do
107+ it "generates SELECT ALL" do
108+ selectAllSQL `shouldEqual` "SELECT * FROM users"
109+ it "generates SELECT WHERE" do
110+ selectWhereSQL `shouldEqual` "SELECT * FROM users WHERE id = $1"