Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/Test1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DataKinds #-}
module Test1 where
import qualified Database.Persist as P
import Database.Persist.TH
Expand Down
1 change: 1 addition & 0 deletions examples/TestODBC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DataKinds #-}
module Main where
import Database.Persist
import Database.Persist.ODBC
Expand Down
12 changes: 6 additions & 6 deletions persistent-odbc.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 1.12
name: persistent-odbc
version: 0.2.1.1
version: 0.3
synopsis: Backend for the persistent library using ODBC
license: MIT
license-file: LICENSE
Expand Down Expand Up @@ -51,8 +51,8 @@ library
, HDBC-odbc >= 2.6.0.0
, monad-logger
, resourcet
, persistent-template >= 2.6.0 && < 2.8.3
, persistent >= 2.6.0 && < 2.11
, persistent-template >= 2.6.0 && < 2.13
, persistent >= 2.12 && < 2.13
, bytestring


Expand All @@ -79,8 +79,8 @@ Executable TestODBC
, HDBC-odbc >= 2.6.0.0
, monad-logger
, resourcet
, persistent-template >= 2.6.0 && < 2.8.3
, persistent >= 2.6.0 && < 2.11
, persistent-template >= 2.6.0 && < 2.13
, persistent >= 2.12 && < 2.13
, bytestring
else
buildable: False
Expand All @@ -91,4 +91,4 @@ Executable TestODBC

source-repository head
type: git
location: git://github.com/gbwey/persistent-odbc.git
location: https://github.com/gbwey/persistent-odbc
186 changes: 101 additions & 85 deletions src/Database/Persist/MigrateDB2.hs

Large diffs are not rendered by default.

176 changes: 96 additions & 80 deletions src/Database/Persist/MigrateMSSQL.hs

Large diffs are not rendered by default.

175 changes: 96 additions & 79 deletions src/Database/Persist/MigrateMySQL.hs

Large diffs are not rendered by default.

178 changes: 98 additions & 80 deletions src/Database/Persist/MigrateOracle.hs

Large diffs are not rendered by default.

168 changes: 94 additions & 74 deletions src/Database/Persist/MigratePostgres.hs

Large diffs are not rendered by default.

34 changes: 19 additions & 15 deletions src/Database/Persist/MigrateSqlite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ getMigrationStrategy dbtype@Sqlite { sqlite3619 = _fksupport } =
{ dbmsLimitOffset=decorateSQLWithLimitOffset "LIMIT -1"
,dbmsMigrate=migrate'
,dbmsInsertSql=insertSql'
,dbmsEscape=escape
,dbmsEscapeFieldName = escape
,dbmsEscapeTableName = escape . entityDB
,dbmsEscapeRawName = escape . FieldNameDB
,dbmsType=dbtype
}
getMigrationStrategy dbtype = error $ "Sqlite: calling with invalid dbtype " ++ show dbtype
Expand Down Expand Up @@ -78,10 +80,11 @@ migrate' :: [EntityDef]
-> EntityDef
-> IO (Either [Text] [(Bool, Text)])
migrate' allDefs getter val = do
let (cols, uniqs, _fdefs) = mkColumns allDefs val
let (cols, uniqs, _fdefs) =
mkColumns allDefs val emptyBackendSpecificOverrides
let newSql = mkCreateTable False def (filter (not . safeToRemove val . cName) cols, uniqs)
stmt <- getter "SELECT sql FROM sqlite_master WHERE type='table' AND name=?"
oldSql' <- with (stmtQuery stmt [PersistText $ unDBName table]) (`connect` go)
oldSql' <- with (stmtQuery stmt [PersistText $ unEntityNameDB table]) (`connect` go)
case oldSql' of
Nothing -> return $ Right [(False, newSql)]
Just oldSql -> do
Expand All @@ -103,10 +106,10 @@ migrate' allDefs getter val = do

-- | Check if a column name is listed as the "safe to remove" in the entity
-- list.
safeToRemove :: EntityDef -> DBName -> Bool
safeToRemove def (DBName colName)
= any (elem "SafeToRemove" . fieldAttrs)
$ filter ((== (DBName colName)) . fieldDB)
safeToRemove :: EntityDef -> FieldNameDB -> Bool
safeToRemove def colName
= any (elem FieldAttrSafeToRemove . fieldAttrs)
$ filter ((== colName) . fieldDB)
$ entityFields def

getCopyTable :: [EntityDef]
Expand All @@ -116,7 +119,7 @@ getCopyTable :: [EntityDef]
getCopyTable allDefs getter def = do
stmt <- getter $ pack $ "PRAGMA table_info(" ++ escape' table ++ ")"
oldCols' <- with (stmtQuery stmt []) (`connect` getCols)
let oldCols = map DBName $ filter (/= "id") oldCols' -- need to update for table id attribute ?
let oldCols = map FieldNameDB $ filter (/= "id") oldCols' -- need to update for table id attribute ?
let newCols = filter (not . safeToRemove def) $ map cName cols
let common = filter (`elem` oldCols) newCols
let id_ = fieldDB (entityId def)
Expand All @@ -137,8 +140,8 @@ getCopyTable allDefs getter def = do
return $ name : names
Just y -> error $ "Invalid result from PRAGMA table_info: " ++ show y
table = entityDB def
tableTmp = DBName $ unDBName table <> "_backup"
(cols, uniqs, _) = mkColumns allDefs def
tableTmp = EntityNameDB $ unEntityNameDB table <> "_backup"
(cols, uniqs, _) = mkColumns allDefs def emptyBackendSpecificOverrides
cols' = filter (not . safeToRemove def . cName) cols
newSql = mkCreateTable False def (cols', uniqs)
tmpSql = mkCreateTable True def { entityDB = tableTmp } (cols', uniqs)
Expand All @@ -164,7 +167,7 @@ getCopyTable allDefs getter def = do
]


escape' :: DBName -> String
escape' :: DatabaseName name => name -> String
escape' = T.unpack . escape

mkCreateTable :: Bool -> EntityDef -> ([Column], [UniqueDef]) -> Text
Expand Down Expand Up @@ -206,7 +209,7 @@ mayDefault def = case def of
Just d -> " DEFAULT " <> d

sqlColumn :: Column -> Text
sqlColumn (Column name isNull typ def _cn _maxLen ref) = T.concat
sqlColumn (Column name isNull typ def _generated _cn _maxLen ref) = T.concat
[ ","
, escape name
, " "
Expand All @@ -217,7 +220,7 @@ sqlColumn (Column name isNull typ def _cn _maxLen ref) = T.concat
Just d -> " DEFAULT " `T.append` d
, case ref of
Nothing -> ""
Just (table, _) -> " REFERENCES " `T.append` escape table
Just colRef -> " REFERENCES " `T.append` escape (crTableName colRef)
]

sqlUnique :: UniqueDef -> Text
Expand All @@ -229,8 +232,9 @@ sqlUnique (UniqueDef _ cname cols _) = T.concat
, ")"
]

escape :: DBName -> Text
escape (DBName s) =
escape :: DatabaseName name => name -> Text
escape =
escapeWith $ \s ->
T.concat [q, T.concatMap go s, q]
where
q = T.singleton '"'
Expand Down
10 changes: 6 additions & 4 deletions src/Database/Persist/ODBC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ type ConnectionString = String
-- finishes using it. Note that you should not use the given
-- 'ConnectionPool' outside the action since it may be already
-- been released.
withODBCPool :: (MonadUnliftIO m, MonadLogger m)
withODBCPool :: (MonadUnliftIO m, MonadLoggerIO m)
=> Maybe DBType
-> ConnectionString
-- ^ Connection string to the database.
Expand All @@ -78,7 +78,7 @@ withODBCPool dbt ci = withSqlPool (\lg -> open' lg dbt ci)
-- responsibility to properly close the connection pool when
-- unneeded. Use 'withODBCPool' for an automatic resource
-- control.
createODBCPool :: (MonadUnliftIO m, MonadLogger m)
createODBCPool :: (MonadUnliftIO m, MonadLoggerIO m)
=> Maybe DBType
-> ConnectionString
-- ^ Connection string to the database.
Expand All @@ -90,7 +90,7 @@ createODBCPool dbt ci = createSqlPool (\lg -> open' lg dbt ci)

-- | Same as 'withODBCPool', but instead of opening a pool
-- of connections, only one connection is opened.
withODBCConn :: (MonadUnliftIO m, MonadLogger m)
withODBCConn :: (MonadUnliftIO m, MonadLoggerIO m)
=> Maybe DBType -> ConnectionString -> (SqlBackend -> m a) -> m a
withODBCConn dbt cs = withSqlConn (\lg -> open' lg dbt cs)

Expand Down Expand Up @@ -142,7 +142,9 @@ openSimpleConn logFunc mdbtype conn = do
-- Transaction begining means that previous commited
, connCommit = const $ O.commit conn
, connRollback = const $ O.rollback conn
, connEscapeName = dbmsEscape mig
, connEscapeFieldName = dbmsEscapeFieldName mig
, connEscapeTableName = dbmsEscapeTableName mig
, connEscapeRawName = dbmsEscapeRawName mig
, connNoLimit = "" -- esqueleto uses this but needs to use connLimitOffset then we can dump this field
, connRDBMS = T.pack $ show (dbmsType mig)
, connLimitOffset = dbmsLimitOffset mig
Expand Down
4 changes: 3 additions & 1 deletion src/Database/Persist/ODBCTypes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ data MigrationStrategy = MigrationStrategy {
dbmsLimitOffset :: (Int,Int) -> Bool -> Text -> Text
,dbmsMigrate :: [EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])
,dbmsInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
,dbmsEscape :: DBName -> Text
,dbmsEscapeFieldName :: FieldNameDB -> Text
,dbmsEscapeTableName :: EntityDef -> Text
,dbmsEscapeRawName :: Text -> Text
,dbmsType :: DBType
}