Skip to content

Commit 2b7f0e4

Browse files
committed
actually parse and compile index type for exclude constraints
1 parent 7645ed0 commit 2b7f0e4

File tree

5 files changed

+115
-11
lines changed

5 files changed

+115
-11
lines changed

IHP/IDE/SchemaDesigner/Compiler.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,18 @@ compileConstraint :: Constraint -> Text
6464
compileConstraint ForeignKeyConstraint { columnName, referenceTable, referenceColumn, onDelete } = "FOREIGN KEY (" <> compileIdentifier columnName <> ") REFERENCES " <> compileIdentifier referenceTable <> (if isJust referenceColumn then " (" <> fromJust referenceColumn <> ")" else "") <> " " <> compileOnDelete onDelete
6565
compileConstraint UniqueConstraint { columnNames } = "UNIQUE(" <> intercalate ", " columnNames <> ")"
6666
compileConstraint CheckConstraint { checkExpression } = "CHECK (" <> compileExpression checkExpression <> ")"
67-
compileConstraint ExcludeConstraint { excludeElements, predicate } = "EXCLUDE (" <> compiledExcludeElements <> ")" <> case predicate of
67+
compileConstraint ExcludeConstraint { excludeElements, predicate, indexType } = "EXCLUDE" <> compiledIndexType <> " (" <> compiledExcludeElements <> ")" <> case predicate of
6868
Just expression -> " WHERE (" <> compileExpression expression <> ")"
6969
Nothing -> ""
7070
where
7171
compiledExcludeElements = intercalate ", " $ map compileExcludeElement excludeElements
7272

7373
compileExcludeElement ExcludeConstraintElement { element, operator } = element <> " WITH " <> operator
7474

75+
compiledIndexType = case indexType of
76+
Nothing -> ""
77+
Just indexType -> " USING " <> compileIndexType indexType
78+
7579
compileDeferrable :: Maybe Bool -> Maybe DeferrableType -> Text
7680
compileDeferrable deferrable deferrableType = Text.concat $ map ((<>) " ") $ catMaybes [compileIsDeferrable <$> deferrable, compileDeferrableType <$> deferrableType]
7781
where

IHP/IDE/SchemaDesigner/Parser.hs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,12 @@ parseCheckConstraint name = do
189189

190190
parseExcludeConstraint name = do
191191
lexeme "EXCLUDE"
192-
optional $ lexeme "USING btree"
192+
indexType <- optional parseIndexType
193193
excludeElements <- between (char '(' >> space) (char ')' >> space) $ excludeElement `sepBy` (char ',' >> space)
194194
predicate <- optional do
195195
lexeme "WHERE"
196196
between (char '(' >> space) (char ')' >> space) expression
197-
pure ExcludeConstraint { name, excludeElements, predicate }
197+
pure ExcludeConstraint { name, excludeElements, predicate, indexType }
198198
where
199199
excludeElement = do
200200
element <- identifier
@@ -547,21 +547,23 @@ createIndex = do
547547
indexName <- identifier
548548
lexeme "ON"
549549
tableName <- qualifiedIdentifier
550-
indexType <- optional do
551-
lexeme "USING"
552-
553-
let btree = do symbol' "btree"; pure Btree
554-
let gin = do symbol' "gin"; pure Gin
555-
let gist = do symbol' "gist"; pure Gist
556-
557-
btree <|> gin <|> gist
550+
indexType <- optional parseIndexType
558551
expressions <- between (char '(' >> space) (char ')' >> space) (expression `sepBy1` (char ',' >> space))
559552
whereClause <- optional do
560553
lexeme "WHERE"
561554
expression
562555
char ';'
563556
pure CreateIndex { indexName, unique, tableName, expressions, whereClause, indexType }
564557

558+
parseIndexType = do
559+
lexeme "USING"
560+
561+
choice $ map (\(s, v) -> do symbol' s; pure v)
562+
[ ("btree", Btree)
563+
, ("gin", Gin)
564+
, ("gist", Gist)
565+
]
566+
565567
createFunction = do
566568
lexeme "CREATE"
567569
orReplace <- isJust <$> optional (lexeme "OR" >> lexeme "REPLACE")

IHP/IDE/SchemaDesigner/Types.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ data Constraint
133133
{ name :: !(Maybe Text)
134134
, excludeElements :: ![ExcludeConstraintElement]
135135
, predicate :: !(Maybe Expression)
136+
, indexType :: !(Maybe IndexType)
136137
}
137138
| AlterTableAddPrimaryKey
138139
{ name :: !(Maybe Text)

Test/IDE/SchemaDesigner/CompilerSpec.hs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,64 @@ tests = do
301301
, ExcludeConstraintElement { element = "author", operator = "=" }
302302
]
303303
, predicate = Nothing
304+
, indexType = Nothing
304305
}
305306
, deferrable = Nothing
306307
, deferrableType = Nothing
307308
}
308309
compileSql [statement] `shouldBe` "ALTER TABLE posts ADD CONSTRAINT unique_title_by_author EXCLUDE (title WITH =, author WITH =);\n"
309310

311+
it "should compile ALTER TABLE .. ADD CONSTRAINT .. EXCLUDE .. USING BTREE" do
312+
let statement = AddConstraint
313+
{ tableName = "posts"
314+
, constraint = ExcludeConstraint
315+
{ name = "unique_title_by_author"
316+
, excludeElements =
317+
[ ExcludeConstraintElement { element = "title", operator = "=" }
318+
, ExcludeConstraintElement { element = "author", operator = "=" }
319+
]
320+
, predicate = Nothing
321+
, indexType = Just Btree
322+
}
323+
, deferrable = Nothing
324+
, deferrableType = Nothing
325+
}
326+
compileSql [statement] `shouldBe` "ALTER TABLE posts ADD CONSTRAINT unique_title_by_author EXCLUDE USING BTREE (title WITH =, author WITH =);\n"
327+
328+
it "should compile ALTER TABLE .. ADD CONSTRAINT .. EXCLUDE .. USING GIST" do
329+
let statement = AddConstraint
330+
{ tableName = "posts"
331+
, constraint = ExcludeConstraint
332+
{ name = "unique_title_by_author"
333+
, excludeElements =
334+
[ ExcludeConstraintElement { element = "title", operator = "=" }
335+
, ExcludeConstraintElement { element = "author", operator = "=" }
336+
]
337+
, predicate = Nothing
338+
, indexType = Just Gist
339+
}
340+
, deferrable = Nothing
341+
, deferrableType = Nothing
342+
}
343+
compileSql [statement] `shouldBe` "ALTER TABLE posts ADD CONSTRAINT unique_title_by_author EXCLUDE USING GIST (title WITH =, author WITH =);\n"
344+
345+
it "should compile ALTER TABLE .. ADD CONSTRAINT .. EXCLUDE .. USING GIN" do
346+
let statement = AddConstraint
347+
{ tableName = "posts"
348+
, constraint = ExcludeConstraint
349+
{ name = "unique_title_by_author"
350+
, excludeElements =
351+
[ ExcludeConstraintElement { element = "title", operator = "=" }
352+
, ExcludeConstraintElement { element = "author", operator = "=" }
353+
]
354+
, predicate = Nothing
355+
, indexType = Just Gin
356+
}
357+
, deferrable = Nothing
358+
, deferrableType = Nothing
359+
}
360+
compileSql [statement] `shouldBe` "ALTER TABLE posts ADD CONSTRAINT unique_title_by_author EXCLUDE USING GIN (title WITH =, author WITH =);\n"
361+
310362
it "should compile ALTER TABLE .. ADD CONSTRAINT .. EXCLUDE .. WHERE .." do
311363
let statement = AddConstraint
312364
{ tableName = "posts"
@@ -317,6 +369,7 @@ tests = do
317369
, ExcludeConstraintElement { element = "author", operator = "=" }
318370
]
319371
, predicate = Just $ EqExpression (VarExpression "title") (TextExpression "why")
372+
, indexType = Nothing
320373
}
321374
, deferrable = Nothing
322375
, deferrableType = Nothing
@@ -336,6 +389,7 @@ tests = do
336389
, ExcludeConstraintElement { element = "i5", operator = "OR" }
337390
]
338391
, predicate = Just $ EqExpression (VarExpression "title") (TextExpression "why")
392+
, indexType = Nothing
339393
}
340394
, deferrable = Nothing
341395
, deferrableType = Nothing
@@ -351,6 +405,7 @@ tests = do
351405
[ ExcludeConstraintElement { element = "title", operator = "=" }
352406
]
353407
, predicate = Nothing
408+
, indexType = Nothing
354409
}
355410
, deferrable = Just True
356411
, deferrableType = Nothing
@@ -366,6 +421,7 @@ tests = do
366421
[ ExcludeConstraintElement { element = "title", operator = "=" }
367422
]
368423
, predicate = Nothing
424+
, indexType = Nothing
369425
}
370426
, deferrable = Just False
371427
, deferrableType = Nothing
@@ -381,6 +437,7 @@ tests = do
381437
[ ExcludeConstraintElement { element = "title", operator = "=" }
382438
]
383439
, predicate = Nothing
440+
, indexType = Nothing
384441
}
385442
, deferrable = Just True
386443
, deferrableType = Just InitiallyImmediate
@@ -396,6 +453,7 @@ tests = do
396453
[ ExcludeConstraintElement { element = "title", operator = "=" }
397454
]
398455
, predicate = Nothing
456+
, indexType = Nothing
399457
}
400458
, deferrable = Just True
401459
, deferrableType = Just InitiallyDeferred

Test/IDE/SchemaDesigner/ParserSpec.hs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ tests = do
343343
, ExcludeConstraintElement { element = "author", operator = "=" }
344344
]
345345
, predicate = Nothing
346+
, indexType = Nothing
346347
}
347348
, deferrable = Nothing
348349
, deferrableType = Nothing
@@ -358,6 +359,39 @@ tests = do
358359
, ExcludeConstraintElement { element = "author", operator = "=" }
359360
]
360361
, predicate = Nothing
362+
, indexType = Just Btree
363+
}
364+
, deferrable = Nothing
365+
, deferrableType = Nothing
366+
}
367+
368+
it "should parse ALTER TABLE .. ADD CONSTRAINT .. EXCLUDE USING gin .." do
369+
parseSql "ALTER TABLE posts ADD CONSTRAINT unique_title_by_author EXCLUDE USING gin (title WITH =, author WITH =);" `shouldBe` AddConstraint
370+
{ tableName = "posts"
371+
, constraint = ExcludeConstraint
372+
{ name = "unique_title_by_author"
373+
, excludeElements =
374+
[ ExcludeConstraintElement { element = "title", operator = "=" }
375+
, ExcludeConstraintElement { element = "author", operator = "=" }
376+
]
377+
, predicate = Nothing
378+
, indexType = Just Gin
379+
}
380+
, deferrable = Nothing
381+
, deferrableType = Nothing
382+
}
383+
384+
it "should parse ALTER TABLE .. ADD CONSTRAINT .. EXCLUDE USING gist .." do
385+
parseSql "ALTER TABLE posts ADD CONSTRAINT unique_title_by_author EXCLUDE USING gist (title WITH =, author WITH =);" `shouldBe` AddConstraint
386+
{ tableName = "posts"
387+
, constraint = ExcludeConstraint
388+
{ name = "unique_title_by_author"
389+
, excludeElements =
390+
[ ExcludeConstraintElement { element = "title", operator = "=" }
391+
, ExcludeConstraintElement { element = "author", operator = "=" }
392+
]
393+
, predicate = Nothing
394+
, indexType = Just Gist
361395
}
362396
, deferrable = Nothing
363397
, deferrableType = Nothing
@@ -373,6 +407,7 @@ tests = do
373407
, ExcludeConstraintElement { element = "author", operator = "=" }
374408
]
375409
, predicate = Just $ EqExpression (VarExpression "title") (TextExpression "why")
410+
, indexType = Nothing
376411
}
377412
, deferrable = Nothing
378413
, deferrableType = Nothing
@@ -391,6 +426,7 @@ tests = do
391426
, ExcludeConstraintElement { element = "i5", operator = "OR" }
392427
]
393428
, predicate = Just $ EqExpression (VarExpression "title") (TextExpression "why")
429+
, indexType = Nothing
394430
}
395431
, deferrable = Nothing
396432
, deferrableType = Nothing
@@ -405,6 +441,7 @@ tests = do
405441
[ ExcludeConstraintElement { element = "title", operator = "=" }
406442
]
407443
, predicate = Nothing
444+
, indexType = Nothing
408445
}
409446
, deferrable = Just True
410447
, deferrableType = Nothing
@@ -419,6 +456,7 @@ tests = do
419456
[ ExcludeConstraintElement { element = "title", operator = "=" }
420457
]
421458
, predicate = Nothing
459+
, indexType = Nothing
422460
}
423461
, deferrable = Just True
424462
, deferrableType = Just InitiallyImmediate
@@ -433,6 +471,7 @@ tests = do
433471
[ ExcludeConstraintElement { element = "title", operator = "=" }
434472
]
435473
, predicate = Nothing
474+
, indexType = Nothing
436475
}
437476
, deferrable = Just True
438477
, deferrableType = Just InitiallyDeferred

0 commit comments

Comments
 (0)