-
Notifications
You must be signed in to change notification settings - Fork 293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Primary
key implies a Unique
constraint
#1383
Changes from 3 commits
ad63d00
36e180e
ac8e418
b7cf9e9
474e776
e5e0f8b
7aa3877
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,3 +37,4 @@ language_extensions: | |
- TemplateHaskell | ||
- TypeApplications | ||
- ViewPatterns | ||
- QuasiQuotes |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,7 @@ module Database.Persist.Quasi.Internal | |
import Prelude hiding (lines) | ||
|
||
import Control.Applicative (Alternative((<|>))) | ||
import Control.Monad | ||
import Data.Char (isLower, isSpace, isUpper, toLower) | ||
import Data.List (find, foldl') | ||
import Data.List.NonEmpty (NonEmpty(..)) | ||
|
@@ -461,7 +462,7 @@ unbindCompositeDef :: CompositeDef -> UnboundCompositeDef | |
unbindCompositeDef cd = | ||
UnboundCompositeDef | ||
{ unboundCompositeCols = | ||
NEL.toList $ fmap fieldHaskell (compositeFields cd) | ||
fmap fieldHaskell (compositeFields cd) | ||
, unboundCompositeAttrs = | ||
compositeAttrs cd | ||
} | ||
|
@@ -984,10 +985,16 @@ takeConstraint ps entityName defs (n :| rest) = | |
Just $ pure (takeForeign ps entityName rest) | ||
} | ||
"Primary" -> | ||
mempty | ||
{ entityConstraintDefsPrimaryComposite = | ||
SetOnce (takeComposite (unboundFieldNameHS <$> defs) rest) | ||
} | ||
let | ||
unboundComposite = | ||
takeComposite (unboundFieldNameHS <$> defs) rest | ||
in | ||
mempty | ||
{ entityConstraintDefsPrimaryComposite = | ||
SetOnce unboundComposite | ||
, entityConstraintDefsUniques = | ||
Just $ pure $ compositeToUniqueDef entityName defs unboundComposite | ||
Comment on lines
+995
to
+996
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the real change. We're adding a |
||
} | ||
"Id" -> | ||
mempty | ||
{ entityConstraintDefsIdField = | ||
|
@@ -1067,7 +1074,7 @@ takeId ps entityName texts = | |
-- | ||
-- @since.2.13.0.0 | ||
data UnboundCompositeDef = UnboundCompositeDef | ||
{ unboundCompositeCols :: [FieldNameHS] | ||
{ unboundCompositeCols :: NonEmpty FieldNameHS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well - we can't have a composite key without at least one field. |
||
-- ^ The field names for the primary key. | ||
-- | ||
-- @since 2.13.0.0 | ||
|
@@ -1079,18 +1086,49 @@ data UnboundCompositeDef = UnboundCompositeDef | |
} | ||
deriving (Eq, Ord, Show, Lift) | ||
|
||
compositeToUniqueDef :: EntityNameHS -> [UnboundFieldDef] -> UnboundCompositeDef -> UniqueDef | ||
compositeToUniqueDef entityName fields UnboundCompositeDef {..} = | ||
UniqueDef | ||
{ uniqueHaskell = | ||
ConstraintNameHS (unEntityNameHS entityName <> "PrimaryKey") | ||
, uniqueDBName = | ||
ConstraintNameDB "primary_key" | ||
, uniqueFields = | ||
fmap (\hsName -> (hsName, getDbNameFor hsName)) unboundCompositeCols | ||
, uniqueAttrs = | ||
unboundCompositeAttrs | ||
} | ||
where | ||
getDbNameFor hsName = | ||
case mapMaybe (matchHsName hsName) fields of | ||
[] -> | ||
error "Unable to find `hsName` in fields" | ||
(a : _) -> | ||
a | ||
matchHsName hsName UnboundFieldDef {..} = do | ||
guard $ unboundFieldNameHS == hsName | ||
pure unboundFieldNameDB | ||
|
||
|
||
|
||
takeComposite | ||
:: [FieldNameHS] | ||
-> [Text] | ||
-> UnboundCompositeDef | ||
takeComposite fields pkcols = | ||
UnboundCompositeDef | ||
{ unboundCompositeCols = | ||
map (getDef fields) cols | ||
fmap (getDef fields) neCols | ||
, unboundCompositeAttrs = | ||
attrs | ||
} | ||
where | ||
neCols = | ||
case NEL.nonEmpty cols of | ||
Nothing -> | ||
error "No fields provided for primary key" | ||
Just xs -> | ||
xs | ||
(cols, attrs) = break ("!" `T.isPrefixOf`) pkcols | ||
getDef [] t = error $ "Unknown column in primary key constraint: " ++ show t | ||
getDef (d:ds) t | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,7 +81,7 @@ mkColumns | |
-> BackendSpecificOverrides | ||
-> ([Column], [UniqueDef], [ForeignDef]) | ||
mkColumns allDefs t overrides = | ||
(cols, getEntityUniques t, getEntityForeignDefs t) | ||
(cols, getEntityUniquesNoPrimaryKey t, getEntityForeignDefs t) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to preserve migration compatibility, we don't return the composite primary key in the |
||
where | ||
cols :: [Column] | ||
cols = map goId idCol `mappend` map go (getEntityFieldsDatabase t) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the old
insertUnique
code was actually broken on this, since it would be totally fine doing aninsert
based on theUniqueBar
being actually unique, but then fail with thePrimary
key constraint violation.