From 54d1e4112a39804445c168291adca036ae708178 Mon Sep 17 00:00:00 2001 From: Ruslan Talpa Date: Fri, 25 Sep 2015 10:30:19 +0300 Subject: [PATCH] detect primary keys for views & use cached info in PUT/PATCH requests --- src/PostgREST/App.hs | 10 ++++++---- src/PostgREST/PgStructure.hs | 16 +++++++++++++++- test/Feature/StructureSpec.hs | 16 ++++++++++++---- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/PostgREST/App.hs b/src/PostgREST/App.hs index c07926d05..dc160fe54 100644 --- a/src/PostgREST/App.hs +++ b/src/PostgREST/App.hs @@ -73,8 +73,8 @@ app dbstructure conf reqBody role req = ([table], "OPTIONS") -> do let qt = Table schema table let cols = filter (filterCol schema table) allColumns - let pkey = map pkName $ filter (filterPk schema table) allPrimaryKeys - let body = encode (TableOptions cols pkey) + let pkeys = map pkName $ filter (filterPk schema table) allPrimaryKeys + let body = encode (TableOptions cols pkeys) return $ responseLBS status200 [jsonH, allOrigins] $ cs body @@ -218,7 +218,8 @@ app dbstructure conf reqBody role req = Right toBeInserted -> do rows :: [Identity Text] <- H.listEx $ uncurry (insertInto qt) toBeInserted let inserted :: [Object] = mapMaybe (decode . cs . runIdentity) rows - primaryKeys <- primaryKeyColumns qt + primaryKeys = map pkName $ filter (filterPk schema table) allPrimaryKeys + --primaryKeys <- primaryKeyColumns qt let responses = flip map inserted $ \obj -> do let primaries = if Prelude.null primaryKeys @@ -252,7 +253,8 @@ app dbstructure conf reqBody role req = ([table], "PUT") -> handleJsonObj reqBody $ \obj -> do let qt = qualify table - primaryKeys <- primaryKeyColumns qt + primaryKeys = map pkName $ filter (filterPk schema table) allPrimaryKeys + --primaryKeys <- primaryKeyColumns qt let specifiedKeys = map (cs . fst) qq if S.fromList primaryKeys /= S.fromList specifiedKeys then return $ responseLBS status405 [] diff --git a/src/PostgREST/PgStructure.hs b/src/PostgREST/PgStructure.hs index 48689cb5f..f56ed6fe5 100644 --- a/src/PostgREST/PgStructure.hs +++ b/src/PostgREST/PgStructure.hs @@ -324,7 +324,9 @@ allcolumns relations = do allprimaryKeys :: H.Tx P.Postgres s [PrimaryKey] allprimaryKeys = do pks <- H.listEx $ [H.stmt| - SELECT kc.table_schema, kc.table_name, kc.column_name + WITH table_pk AS + ( + SELECT kc.table_schema, kc.table_name, kc.column_name FROM information_schema.table_constraints tc, information_schema.key_column_usage kc WHERE tc.constraint_type = 'PRIMARY KEY' @@ -332,6 +334,18 @@ allprimaryKeys = do AND kc.table_schema = tc.table_schema AND kc.constraint_name = tc.constraint_name AND kc.table_schema NOT IN ('pg_catalog', 'information_schema') + ) + SELECT table_schema, table_name, column_name + FROM table_pk + UNION + ( + SELECT vcu.view_schema, vcu.view_name, vcu.column_name + FROM information_schema.view_column_usage AS vcu + JOIN table_pk ON table_pk.table_schema = vcu.view_schema + AND table_pk.table_name = vcu.table_name + AND table_pk.column_name = vcu.column_name + WHERE vcu.view_schema NOT IN ('pg_catalog', 'information_schema') + ) |] return $ map pkFromRow pks diff --git a/test/Feature/StructureSpec.hs b/test/Feature/StructureSpec.hs index d2f6bdb45..eb63e5724 100644 --- a/test/Feature/StructureSpec.hs +++ b/test/Feature/StructureSpec.hs @@ -145,11 +145,13 @@ spec = around withApp $ do } |] - it "it includes primary key for views" $ + it "it includes primary and foreign keys for views" $ request methodOptions "/insertable_view_with_join" [] "" `shouldRespondWith` [json| { - "pkey":["id"], + "pkey":[ + "id" + ], "columns":[ { "references":null, @@ -165,7 +167,10 @@ spec = around withApp $ do "position":1 }, { - "references":null, + "references":{ + "column":"id", + "table":"auto_incrementing_pk" + }, "default":null, "precision":32, "updatable":false, @@ -178,7 +183,10 @@ spec = around withApp $ do "position":2 }, { - "references":null, + "references":{ + "column":"k", + "table":"simple_pk" + }, "default":null, "precision":null, "updatable":false,