Removing single column limit from join table M2M mapping detection. (#1593)
This commit is contained in:
@@ -18,6 +18,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- #1592, Removed single column restriction to allow composite foreign keys in join tables - @goteguru
|
||||||
- #1530, Fix how the PostgREST version is shown in the help text when the `.git` directory is not available - @monacoremo
|
- #1530, Fix how the PostgREST version is shown in the help text when the `.git` directory is not available - @monacoremo
|
||||||
- #1094, Fix expired JWTs starting an empty transaction on the db - @steve-chavez
|
- #1094, Fix expired JWTs starting an empty transaction on the db - @steve-chavez
|
||||||
- #1162, Fix location header for POST request with select= without PK - @wolfgangwalther
|
- #1162, Fix location header for POST request with select= without PK - @wolfgangwalther
|
||||||
|
|||||||
@@ -358,9 +358,9 @@ addO2MRels = concatMap (\rel@(Relation t c cn ft fc _ _) -> [rel, Relation ft fc
|
|||||||
addM2MRels :: [Relation] -> [Relation]
|
addM2MRels :: [Relation] -> [Relation]
|
||||||
addM2MRels rels = rels ++ addMirrorRel (mapMaybe junction2Rel junctions)
|
addM2MRels rels = rels ++ addMirrorRel (mapMaybe junction2Rel junctions)
|
||||||
where
|
where
|
||||||
junctions = join $ map (combinations 2) $ filter (not . null) $ groupWith groupFn $ filter ( (==M2O). relType) rels
|
junctions = join $ map (combinations 2) $ groupWith groupFn $ filter ( (==M2O). relType) rels
|
||||||
groupFn :: Relation -> Text
|
groupFn :: Relation -> (Text,Text)
|
||||||
groupFn Relation{relTable=Table{tableSchema=s, tableName=t}} = s <> "_" <> t
|
groupFn Relation{relTable=Table{tableSchema=s, tableName=t}} = (s,t)
|
||||||
-- Reference : https://wiki.haskell.org/99_questions/Solutions/26
|
-- Reference : https://wiki.haskell.org/99_questions/Solutions/26
|
||||||
combinations :: Int -> [a] -> [[a]]
|
combinations :: Int -> [a] -> [[a]]
|
||||||
combinations 0 _ = [ [] ]
|
combinations 0 _ = [ [] ]
|
||||||
@@ -370,7 +370,7 @@ addM2MRels rels = rels ++ addMirrorRel (mapMaybe junction2Rel junctions)
|
|||||||
Relation{relTable=jt, relColumns=jc1, relConstraint=const1, relFTable=t, relFColumns=c},
|
Relation{relTable=jt, relColumns=jc1, relConstraint=const1, relFTable=t, relFColumns=c},
|
||||||
Relation{ relColumns=jc2, relConstraint=const2, relFTable=ft, relFColumns=fc}
|
Relation{ relColumns=jc2, relConstraint=const2, relFTable=ft, relFColumns=fc}
|
||||||
]
|
]
|
||||||
| jc1 /= jc2 && length jc1 == 1 && length jc2 == 1 = Just $ Relation t c Nothing ft fc M2M (Just $ Junction jt const1 jc1 const2 jc2)
|
| jc1 /= jc2 = Just $ Relation t c Nothing ft fc M2M (Just $ Junction jt const1 jc1 const2 jc2)
|
||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
junction2Rel _ = Nothing
|
junction2Rel _ = Nothing
|
||||||
addMirrorRel = concatMap (\rel@(Relation t c _ ft fc _ (Just (Junction jt const1 jc1 const2 jc2))) ->
|
addMirrorRel = concatMap (\rel@(Relation t c _ ft fc _ (Just (Junction jt const1 jc1 const2 jc2))) ->
|
||||||
|
|||||||
@@ -351,6 +351,21 @@ spec actualPgVersion = do
|
|||||||
[json|[{"id":1,"tasks":[{"id":1},{"id":2},{"id":3},{"id":4}]},{"id":2,"tasks":[{"id":5},{"id":6},{"id":7}]},{"id":3,"tasks":[{"id":1},{"id":5}]}]|]
|
[json|[{"id":1,"tasks":[{"id":1},{"id":2},{"id":3},{"id":4}]},{"id":2,"tasks":[{"id":5},{"id":6},{"id":7}]},{"id":3,"tasks":[{"id":1},{"id":5}]}]|]
|
||||||
{ matchHeaders = [matchContentTypeJson] }
|
{ matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
|
it "requesting many<->many relation using composite key" $
|
||||||
|
get "/files?filename=eq.autoexec.bat&project_id=eq.1&select=filename,users_tasks(user_id,task_id)" `shouldRespondWith`
|
||||||
|
[json|[{"filename":"autoexec.bat","users_tasks":[{"user_id":1,"task_id":1},{"user_id":3,"task_id":1}]}]|]
|
||||||
|
{ matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
|
it "requesting data using many<->many relation defined by composite keys" $
|
||||||
|
get "/users_tasks?user_id=eq.1&task_id=eq.1&select=user_id,files(filename,content)" `shouldRespondWith`
|
||||||
|
[json|[{"user_id":1,"files":[{"filename":"command.com","content":"#include <unix.h>"},{"filename":"autoexec.bat","content":"@ECHO OFF"},{"filename":"README.md","content":"# make $$$!"}]}]|]
|
||||||
|
{ matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
|
it "requesting data using many<->many (composite keys) relation using hint" $
|
||||||
|
get "/users_tasks?user_id=eq.1&task_id=eq.1&select=user_id,files!touched_files(filename,content)" `shouldRespondWith`
|
||||||
|
[json|[{"user_id":1,"files":[{"filename":"command.com","content":"#include <unix.h>"},{"filename":"autoexec.bat","content":"@ECHO OFF"},{"filename":"README.md","content":"# make $$$!"}]}]|]
|
||||||
|
{ matchHeaders = [matchContentTypeJson] }
|
||||||
|
|
||||||
it "requesting children with composite key" $
|
it "requesting children with composite key" $
|
||||||
get "/users_tasks?user_id=eq.2&task_id=eq.6&select=*, comments(content)" `shouldRespondWith`
|
get "/users_tasks?user_id=eq.2&task_id=eq.6&select=*, comments(content)" `shouldRespondWith`
|
||||||
[json|[{"user_id":2,"task_id":6,"comments":[{"content":"Needs to be delivered ASAP"}]}]|]
|
[json|[{"user_id":2,"task_id":6,"comments":[{"content":"Needs to be delivered ASAP"}]}]|]
|
||||||
|
|||||||
Vendored
+20
@@ -140,6 +140,26 @@ INSERT INTO users_tasks VALUES (3, 5);
|
|||||||
TRUNCATE TABLE comments CASCADE;
|
TRUNCATE TABLE comments CASCADE;
|
||||||
INSERT INTO comments VALUES (1, 1, 2, 6, 'Needs to be delivered ASAP');
|
INSERT INTO comments VALUES (1, 1, 2, 6, 'Needs to be delivered ASAP');
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Data for Name: files; Type: TABLE DATA; Schema: test; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
TRUNCATE TABLE files CASCADE;
|
||||||
|
INSERT INTO files VALUES
|
||||||
|
(1, 'command.com', '#include <unix.h>')
|
||||||
|
,(1, 'autoexec.bat', '@ECHO OFF')
|
||||||
|
,(1, 'io.sys', 'TODO')
|
||||||
|
,(2, 'README.md', '# make $$$!')
|
||||||
|
,(2, 'marketing.key', '$-$')
|
||||||
|
;
|
||||||
|
|
||||||
|
TRUNCATE TABLE touched_files CASCADE;
|
||||||
|
INSERT INTO touched_files VALUES
|
||||||
|
(1, 1, 1, 'command.com')
|
||||||
|
,(1, 1, 1, 'autoexec.bat')
|
||||||
|
,(1, 1, 2, 'README.md')
|
||||||
|
,(3, 1, 1, 'autoexec.bat')
|
||||||
|
;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Data for Name: complex_items; Type: TABLE DATA; Schema: test; Owner: -
|
-- Data for Name: complex_items; Type: TABLE DATA; Schema: test; Owner: -
|
||||||
|
|||||||
Vendored
+2
@@ -43,6 +43,8 @@ GRANT ALL ON TABLE
|
|||||||
, users
|
, users
|
||||||
, users_projects
|
, users_projects
|
||||||
, users_tasks
|
, users_tasks
|
||||||
|
, files
|
||||||
|
, touched_files
|
||||||
, "Escap3e;"
|
, "Escap3e;"
|
||||||
, "ghostBusters"
|
, "ghostBusters"
|
||||||
, "withUnique"
|
, "withUnique"
|
||||||
|
|||||||
Vendored
+22
@@ -697,6 +697,28 @@ alter table only comments
|
|||||||
add constraint "user" foreign key (commenter_id) references users(id),
|
add constraint "user" foreign key (commenter_id) references users(id),
|
||||||
add constraint comments_task_id_fkey foreign key (task_id, user_id) references users_tasks(task_id, user_id);
|
add constraint comments_task_id_fkey foreign key (task_id, user_id) references users_tasks(task_id, user_id);
|
||||||
|
|
||||||
|
CREATE TABLE files (
|
||||||
|
project_id integer NOT NULL,
|
||||||
|
filename text NOT NULL,
|
||||||
|
content text NOT NULL,
|
||||||
|
PRIMARY KEY (project_id, filename)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE touched_files (
|
||||||
|
user_id integer NOT NULL,
|
||||||
|
task_id integer NOT NULL,
|
||||||
|
project_id integer NOT NULL,
|
||||||
|
filename text NOT NULL,
|
||||||
|
CONSTRAINT fk_users_tasks
|
||||||
|
FOREIGN KEY (user_id, task_id)
|
||||||
|
REFERENCES users_tasks (user_id, task_id)
|
||||||
|
ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT fk_upload
|
||||||
|
FOREIGN KEY (project_id, filename)
|
||||||
|
REFERENCES files (project_id,filename)
|
||||||
|
ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
create table private.articles (
|
create table private.articles (
|
||||||
id integer primary key,
|
id integer primary key,
|
||||||
body text,
|
body text,
|
||||||
|
|||||||
Reference in New Issue
Block a user