feat: Added --dump-schema CLI option to dump JSON of dbStructure schema cache.
Added postgrest-dump-schema to nix-shell returning a YAML dump of the test fixtures. Authored-by: monacoremo <monacoremo>
This commit is contained in:
+65
-5
@@ -1,11 +1,14 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
module Main where
|
module Main (main) where
|
||||||
|
|
||||||
|
import qualified Data.Aeson as Aeson
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
import qualified Hasql.Connection as C
|
import qualified Hasql.Connection as C
|
||||||
import qualified Hasql.Notifications as N
|
import qualified Hasql.Notifications as N
|
||||||
import qualified Hasql.Pool as P
|
import qualified Hasql.Pool as P
|
||||||
|
import qualified Hasql.Session as S
|
||||||
import qualified Hasql.Transaction.Sessions as HT
|
import qualified Hasql.Transaction.Sessions as HT
|
||||||
|
|
||||||
import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate,
|
import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate,
|
||||||
@@ -24,7 +27,9 @@ import Data.Text.IO (hPutStrLn)
|
|||||||
import Data.Time.Clock (getCurrentTime)
|
import Data.Time.Clock (getCurrentTime)
|
||||||
import Network.Wai.Handler.Warp (defaultSettings, runSettings,
|
import Network.Wai.Handler.Warp (defaultSettings, runSettings,
|
||||||
setHost, setPort, setServerName)
|
setHost, setPort, setServerName)
|
||||||
|
import System.CPUTime (getCPUTime)
|
||||||
import System.IO (BufferMode (..), hSetBuffering)
|
import System.IO (BufferMode (..), hSetBuffering)
|
||||||
|
import Text.Printf (hPrintf)
|
||||||
|
|
||||||
import PostgREST.App (postgrest)
|
import PostgREST.App (postgrest)
|
||||||
import PostgREST.Config (AppConfig (..), CLI (..), Command (..),
|
import PostgREST.Config (AppConfig (..), CLI (..), Command (..),
|
||||||
@@ -64,9 +69,6 @@ main = do
|
|||||||
-- build the 'AppConfig' from the config file path
|
-- build the 'AppConfig' from the config file path
|
||||||
conf <- readValidateConfig $ cliPath opts
|
conf <- readValidateConfig $ cliPath opts
|
||||||
|
|
||||||
-- dump config and exit if option is set
|
|
||||||
when (cliCommand opts == CmdDumpConfig) $ dumpAppConfig conf
|
|
||||||
|
|
||||||
-- These are config values that can't be reloaded at runtime. Reloading some of them would imply restarting the web server.
|
-- These are config values that can't be reloaded at runtime. Reloading some of them would imply restarting the web server.
|
||||||
let
|
let
|
||||||
host = configServerHost conf
|
host = configServerHost conf
|
||||||
@@ -86,6 +88,19 @@ main = do
|
|||||||
poolTimeout = configDbPoolTimeout' conf
|
poolTimeout = configDbPoolTimeout' conf
|
||||||
logLevel = configLogLevel conf
|
logLevel = configLogLevel conf
|
||||||
|
|
||||||
|
case cliCommand opts of
|
||||||
|
CmdDumpConfig ->
|
||||||
|
do
|
||||||
|
putStr $ dumpAppConfig conf
|
||||||
|
exitSuccess
|
||||||
|
CmdDumpSchema ->
|
||||||
|
do
|
||||||
|
dumpedSchema <- dumpSchema conf
|
||||||
|
putStrLn dumpedSchema
|
||||||
|
exitSuccess
|
||||||
|
CmdRun ->
|
||||||
|
pass
|
||||||
|
|
||||||
-- create connection pool with the provided settings, returns either a 'Connection' or a 'ConnectionError'. Does not throw.
|
-- create connection pool with the provided settings, returns either a 'Connection' or a 'ConnectionError'. Does not throw.
|
||||||
pool <- P.acquire (poolSize, poolTimeout, dbUri)
|
pool <- P.acquire (poolSize, poolTimeout, dbUri)
|
||||||
|
|
||||||
@@ -158,6 +173,7 @@ main = do
|
|||||||
putStrLn $ ("Listening on port " :: Text) <> show port
|
putStrLn $ ("Listening on port " :: Text) <> show port
|
||||||
runSettings serverSettings postgrestApplication
|
runSettings serverSettings postgrestApplication
|
||||||
|
|
||||||
|
|
||||||
-- Time constants
|
-- Time constants
|
||||||
_32s :: Int
|
_32s :: Int
|
||||||
_32s = 32000000 :: Int -- 32 seconds
|
_32s = 32000000 :: Int -- 32 seconds
|
||||||
@@ -316,16 +332,60 @@ listener dbUri dbChannel pool refConf refDbStructure mvarConnectionStatus connWo
|
|||||||
|
|
||||||
-- | Re-reads the config at runtime. Invoked on SIGUSR2.
|
-- | Re-reads the config at runtime. Invoked on SIGUSR2.
|
||||||
-- | If it panics(config path was changed, invalid setting), it'll show an error but won't kill the main thread.
|
-- | If it panics(config path was changed, invalid setting), it'll show an error but won't kill the main thread.
|
||||||
|
#ifndef mingw32_HOST_OS
|
||||||
reReadConfig :: FilePath -> IORef AppConfig -> IO ()
|
reReadConfig :: FilePath -> IORef AppConfig -> IO ()
|
||||||
reReadConfig path refConf = do
|
reReadConfig path refConf = do
|
||||||
conf <- readValidateConfig path
|
conf <- readValidateConfig path
|
||||||
atomicWriteIORef refConf conf
|
atomicWriteIORef refConf conf
|
||||||
putStrLn ("Config file reloaded" :: Text)
|
putStrLn ("Config file reloaded" :: Text)
|
||||||
|
#endif
|
||||||
|
|
||||||
-- Utilitarian functions.
|
-- | Dump DbStructure schema to JSON
|
||||||
|
dumpSchema :: AppConfig -> IO LBS.ByteString
|
||||||
|
dumpSchema conf =
|
||||||
|
do
|
||||||
|
Right conn <- C.acquire . toS $ configDbUri conf
|
||||||
|
Right pgVersion <- S.run getPgVersion conn
|
||||||
|
let
|
||||||
|
getDbStructureTransaction =
|
||||||
|
HT.transaction HT.ReadCommitted HT.Read $
|
||||||
|
getDbStructure
|
||||||
|
(toList $ configDbSchemas conf)
|
||||||
|
(configDbExtraSearchPath conf)
|
||||||
|
pgVersion
|
||||||
|
(configDbPreparedStatements conf)
|
||||||
|
Right dbStructure <-
|
||||||
|
timeToStderr "Loaded schema in %.3f seconds" $
|
||||||
|
S.run getDbStructureTransaction conn
|
||||||
|
C.release conn
|
||||||
|
return $ Aeson.encode dbStructure
|
||||||
|
|
||||||
|
|
||||||
|
-- | Print the time taken to run an IO action to stderr with the given printf string
|
||||||
|
timeToStderr :: [Char] -> IO a -> IO a
|
||||||
|
timeToStderr fmtString a =
|
||||||
|
do
|
||||||
|
start <- getCPUTime
|
||||||
|
result <- a
|
||||||
|
end <- getCPUTime
|
||||||
|
let
|
||||||
|
duration :: Double
|
||||||
|
duration = fromIntegral (end - start) / picoseconds
|
||||||
|
hPrintf stderr (fmtString ++ "\n") duration
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
-- | 10^12 picoseconds per second
|
||||||
|
picoseconds :: Double
|
||||||
|
picoseconds = 1000000000000
|
||||||
|
|
||||||
|
|
||||||
|
-- Utility functions.
|
||||||
|
#ifndef mingw32_HOST_OS
|
||||||
whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f ()
|
whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f ()
|
||||||
whenJust (Just x) f = f x
|
whenJust (Just x) f = f x
|
||||||
whenJust Nothing _ = pass
|
whenJust Nothing _ = pass
|
||||||
|
#endif
|
||||||
|
|
||||||
whenNothing :: Applicative f => Maybe a -> f () -> f ()
|
whenNothing :: Applicative f => Maybe a -> f () -> f ()
|
||||||
whenNothing Nothing f = f
|
whenNothing Nothing f = f
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
, procps
|
, procps
|
||||||
, python3
|
, python3
|
||||||
, runtimeShell
|
, runtimeShell
|
||||||
|
, yq
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
# Wrap the `test/with_tmp_db` script with the required dependencies from Nix.
|
# Wrap the `test/with_tmp_db` script with the required dependencies from Nix.
|
||||||
@@ -125,6 +126,23 @@ let
|
|||||||
|
|
||||||
${withTmpDb postgresql} "$rootdir/test/memory-tests.sh"
|
${withTmpDb postgresql} "$rootdir/test/memory-tests.sh"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
dumpSchema =
|
||||||
|
name: postgresql:
|
||||||
|
checkedShellScript
|
||||||
|
name
|
||||||
|
''
|
||||||
|
rootdir="$(${git}/bin/git rev-parse --show-toplevel)"
|
||||||
|
cd "$rootdir"
|
||||||
|
|
||||||
|
env="$(cat ${postgrest.env})"
|
||||||
|
export PATH="$env/bin:$PATH"
|
||||||
|
|
||||||
|
${withTmpDb postgresql} \
|
||||||
|
${cabal-install}/bin/cabal v2-run ${devCabalOptions} --verbose=0 -- \
|
||||||
|
postgrest --dump-schema "$rootdir"/test/io-tests/configs/simple.config \
|
||||||
|
| ${yq}/bin/yq -y .
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
# Create an environment that contains all the utility scripts for running tests
|
# Create an environment that contains all the utility scripts for running tests
|
||||||
# that we defined above.
|
# that we defined above.
|
||||||
@@ -139,6 +157,7 @@ buildEnv
|
|||||||
(testSpecIdempotence "postgrest-test-spec-idempotence" postgresql).bin
|
(testSpecIdempotence "postgrest-test-spec-idempotence" postgresql).bin
|
||||||
testSpecAllVersions.bin
|
testSpecAllVersions.bin
|
||||||
(testIO "postgrest-test-io" postgresql).bin
|
(testIO "postgrest-test-io" postgresql).bin
|
||||||
|
(dumpSchema "postgrest-dump-schema" postgresql).bin
|
||||||
] ++ testSpecVersions;
|
] ++ testSpecVersions;
|
||||||
}
|
}
|
||||||
# The memory tests have large dependencies (a profiled build of PostgREST)
|
# The memory tests have large dependencies (a profiled build of PostgREST)
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ executable postgrest
|
|||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
hs-source-dirs: main
|
hs-source-dirs: main
|
||||||
build-depends: base >= 4.9 && < 4.15
|
build-depends: base >= 4.9 && < 4.15
|
||||||
|
, aeson >= 1.4.7 && < 1.6
|
||||||
, auto-update >= 0.1.4 && < 0.2
|
, auto-update >= 0.1.4 && < 0.2
|
||||||
, base64-bytestring >= 1 && < 1.3
|
, base64-bytestring >= 1 && < 1.3
|
||||||
, bytestring >= 0.10.8 && < 0.11
|
, bytestring >= 0.10.8 && < 0.11
|
||||||
|
|||||||
+18
-10
@@ -76,7 +76,11 @@ data CLI = CLI
|
|||||||
{ cliCommand :: Command
|
{ cliCommand :: Command
|
||||||
, cliPath :: FilePath }
|
, cliPath :: FilePath }
|
||||||
|
|
||||||
data Command = CmdRun | CmdDumpConfig deriving (Eq)
|
data Command
|
||||||
|
= CmdRun
|
||||||
|
| CmdDumpConfig
|
||||||
|
| CmdDumpSchema
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
-- | Config file settings for the server
|
-- | Config file settings for the server
|
||||||
data AppConfig = AppConfig {
|
data AppConfig = AppConfig {
|
||||||
@@ -148,10 +152,18 @@ readCLIShowHelp = customExecParser parserPrefs opts
|
|||||||
|
|
||||||
cliParser :: Parser CLI
|
cliParser :: Parser CLI
|
||||||
cliParser = CLI <$>
|
cliParser = CLI <$>
|
||||||
|
(
|
||||||
flag CmdRun CmdDumpConfig (
|
flag CmdRun CmdDumpConfig (
|
||||||
long "dump-config" <>
|
long "dump-config" <>
|
||||||
help "Dump loaded configuration and exit"
|
help "Dump loaded configuration and exit"
|
||||||
) <*>
|
)
|
||||||
|
<|>
|
||||||
|
flag CmdRun CmdDumpSchema (
|
||||||
|
long "dump-schema" <>
|
||||||
|
help "Dump loaded schema as JSON and exit (for debugging, output structure is unstable)"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*>
|
||||||
strArgument (
|
strArgument (
|
||||||
metavar "FILENAME" <>
|
metavar "FILENAME" <>
|
||||||
help "Path to configuration file"
|
help "Path to configuration file"
|
||||||
@@ -237,15 +249,11 @@ readCLIShowHelp = customExecParser parserPrefs opts
|
|||||||
|]
|
|]
|
||||||
|
|
||||||
-- | Dump the config
|
-- | Dump the config
|
||||||
dumpAppConfig :: AppConfig -> IO ()
|
dumpAppConfig :: AppConfig -> Text
|
||||||
dumpAppConfig conf = do
|
dumpAppConfig conf =
|
||||||
putStr dump
|
unlines $ (\(k, v) -> k <> " = " <> v) <$>
|
||||||
exitSuccess
|
|
||||||
|
|
||||||
where
|
|
||||||
dump = unlines $ (\(k, v) -> k <> " = " <> v) <$>
|
|
||||||
pgrstSettings ++ appSettings
|
pgrstSettings ++ appSettings
|
||||||
|
where
|
||||||
-- apply conf to all pgrst settings
|
-- apply conf to all pgrst settings
|
||||||
pgrstSettings = (\(k, v) -> (k, v conf)) <$>
|
pgrstSettings = (\(k, v) -> (k, v conf)) <$>
|
||||||
[("db-anon-role", q . configDbAnonRole)
|
[("db-anon-role", q . configDbAnonRole)
|
||||||
|
|||||||
+16
-15
@@ -2,6 +2,7 @@
|
|||||||
Module : PostgREST.Types
|
Module : PostgREST.Types
|
||||||
Description : PostgREST common types and functions used by the rest of the modules
|
Description : PostgREST common types and functions used by the rest of the modules
|
||||||
-}
|
-}
|
||||||
|
{-# LANGUAGE DeriveAnyClass #-}
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ data DbStructure = DbStructure {
|
|||||||
, dbPrimaryKeys :: [PrimaryKey]
|
, dbPrimaryKeys :: [PrimaryKey]
|
||||||
, dbProcs :: ProcsMap
|
, dbProcs :: ProcsMap
|
||||||
, pgVersion :: PgVersion
|
, pgVersion :: PgVersion
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
-- TODO Table could hold references to all its Columns
|
-- TODO Table could hold references to all its Columns
|
||||||
tableCols :: DbStructure -> Schema -> TableName -> [Column]
|
tableCols :: DbStructure -> Schema -> TableName -> [Column]
|
||||||
@@ -140,14 +141,14 @@ data PgArg = PgArg {
|
|||||||
, pgaType :: Text
|
, pgaType :: Text
|
||||||
, pgaReq :: Bool
|
, pgaReq :: Bool
|
||||||
, pgaVar :: Bool
|
, pgaVar :: Bool
|
||||||
} deriving (Show, Eq, Ord)
|
} deriving (Show, Eq, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
data PgType = Scalar QualifiedIdentifier | Composite QualifiedIdentifier deriving (Eq, Show, Ord)
|
data PgType = Scalar QualifiedIdentifier | Composite QualifiedIdentifier deriving (Eq, Show, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
data RetType = Single PgType | SetOf PgType deriving (Eq, Show, Ord)
|
data RetType = Single PgType | SetOf PgType deriving (Eq, Show, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
data ProcVolatility = Volatile | Stable | Immutable
|
data ProcVolatility = Volatile | Stable | Immutable
|
||||||
deriving (Eq, Show, Ord)
|
deriving (Eq, Show, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
data ProcDescription = ProcDescription {
|
data ProcDescription = ProcDescription {
|
||||||
pdSchema :: Schema
|
pdSchema :: Schema
|
||||||
@@ -157,7 +158,7 @@ data ProcDescription = ProcDescription {
|
|||||||
, pdReturnType :: RetType
|
, pdReturnType :: RetType
|
||||||
, pdVolatility :: ProcVolatility
|
, pdVolatility :: ProcVolatility
|
||||||
, pdHasVariadic :: Bool
|
, pdHasVariadic :: Bool
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
-- Order by least number of args in the case of overloaded functions
|
-- Order by least number of args in the case of overloaded functions
|
||||||
instance Ord ProcDescription where
|
instance Ord ProcDescription where
|
||||||
@@ -225,7 +226,7 @@ data Table = Table {
|
|||||||
, tableName :: TableName
|
, tableName :: TableName
|
||||||
, tableDescription :: Maybe Text
|
, tableDescription :: Maybe Text
|
||||||
, tableInsertable :: Bool
|
, tableInsertable :: Bool
|
||||||
} deriving (Show, Ord)
|
} deriving (Show, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
instance Eq Table where
|
instance Eq Table where
|
||||||
Table{tableSchema=s1,tableName=n1} == Table{tableSchema=s2,tableName=n2} = s1 == s2 && n1 == n2
|
Table{tableSchema=s1,tableName=n1} == Table{tableSchema=s2,tableName=n2} = s1 == s2 && n1 == n2
|
||||||
@@ -233,7 +234,7 @@ instance Eq Table where
|
|||||||
tableQi :: Table -> QualifiedIdentifier
|
tableQi :: Table -> QualifiedIdentifier
|
||||||
tableQi Table{tableSchema=s, tableName=n} = QualifiedIdentifier s n
|
tableQi Table{tableSchema=s, tableName=n} = QualifiedIdentifier s n
|
||||||
|
|
||||||
newtype ForeignKey = ForeignKey { fkCol :: Column } deriving (Show, Eq, Ord)
|
newtype ForeignKey = ForeignKey { fkCol :: Column } deriving (Show, Eq, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
data Column =
|
data Column =
|
||||||
Column {
|
Column {
|
||||||
@@ -249,7 +250,7 @@ data Column =
|
|||||||
, colDefault :: Maybe Text
|
, colDefault :: Maybe Text
|
||||||
, colEnum :: [Text]
|
, colEnum :: [Text]
|
||||||
, colFK :: Maybe ForeignKey
|
, colFK :: Maybe ForeignKey
|
||||||
} deriving (Show, Ord)
|
} deriving (Show, Ord, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
instance Eq Column where
|
instance Eq Column where
|
||||||
Column{colTable=t1,colName=n1} == Column{colTable=t2,colName=n2} = t1 == t2 && n1 == n2
|
Column{colTable=t1,colName=n1} == Column{colTable=t2,colName=n2} = t1 == t2 && n1 == n2
|
||||||
@@ -261,7 +262,7 @@ type ViewColumn = Column
|
|||||||
data PrimaryKey = PrimaryKey {
|
data PrimaryKey = PrimaryKey {
|
||||||
pkTable :: Table
|
pkTable :: Table
|
||||||
, pkName :: Text
|
, pkName :: Text
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
data OrderDirection = OrderAsc | OrderDesc deriving (Eq)
|
data OrderDirection = OrderAsc | OrderDesc deriving (Eq)
|
||||||
instance Show OrderDirection where
|
instance Show OrderDirection where
|
||||||
@@ -286,7 +287,7 @@ data OrderTerm = OrderTerm {
|
|||||||
data QualifiedIdentifier = QualifiedIdentifier {
|
data QualifiedIdentifier = QualifiedIdentifier {
|
||||||
qiSchema :: Schema
|
qiSchema :: Schema
|
||||||
, qiName :: TableName
|
, qiName :: TableName
|
||||||
} deriving (Show, Eq, Ord, Generic)
|
} deriving (Show, Eq, Ord, Generic, JSON.ToJSON, JSON.ToJSONKey)
|
||||||
instance Hashable QualifiedIdentifier
|
instance Hashable QualifiedIdentifier
|
||||||
|
|
||||||
-- | The relationship [cardinality](https://en.wikipedia.org/wiki/Cardinality_(data_modeling)).
|
-- | The relationship [cardinality](https://en.wikipedia.org/wiki/Cardinality_(data_modeling)).
|
||||||
@@ -294,7 +295,7 @@ instance Hashable QualifiedIdentifier
|
|||||||
data Cardinality = O2M -- ^ one-to-many, previously known as Parent
|
data Cardinality = O2M -- ^ one-to-many, previously known as Parent
|
||||||
| M2O -- ^ many-to-one, previously known as Child
|
| M2O -- ^ many-to-one, previously known as Child
|
||||||
| M2M -- ^ many-to-many, previously known as Many
|
| M2M -- ^ many-to-many, previously known as Many
|
||||||
deriving Eq
|
deriving (Eq, Generic, JSON.ToJSON)
|
||||||
instance Show Cardinality where
|
instance Show Cardinality where
|
||||||
show O2M = "o2m"
|
show O2M = "o2m"
|
||||||
show M2O = "m2o"
|
show M2O = "m2o"
|
||||||
@@ -315,7 +316,7 @@ data Relation = Relation {
|
|||||||
, relFColumns :: [Column]
|
, relFColumns :: [Column]
|
||||||
, relType :: Cardinality
|
, relType :: Cardinality
|
||||||
, relJunction :: Maybe Junction -- ^ Junction for M2M Cardinality
|
, relJunction :: Maybe Junction -- ^ Junction for M2M Cardinality
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
-- | Junction table on an M2M relationship
|
-- | Junction table on an M2M relationship
|
||||||
data Junction = Junction {
|
data Junction = Junction {
|
||||||
@@ -324,7 +325,7 @@ data Junction = Junction {
|
|||||||
, junCols1 :: [Column]
|
, junCols1 :: [Column]
|
||||||
, junConstraint2 :: Maybe ConstraintName
|
, junConstraint2 :: Maybe ConstraintName
|
||||||
, junCols2 :: [Column]
|
, junCols2 :: [Column]
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
isSelfReference :: Relation -> Bool
|
isSelfReference :: Relation -> Bool
|
||||||
isSelfReference r = relTable r == relFTable r
|
isSelfReference r = relTable r == relFTable r
|
||||||
@@ -510,7 +511,7 @@ fstFieldNames (Node (sel, _) _) =
|
|||||||
data PgVersion = PgVersion {
|
data PgVersion = PgVersion {
|
||||||
pgvNum :: Int32
|
pgvNum :: Int32
|
||||||
, pgvName :: Text
|
, pgvName :: Text
|
||||||
} deriving (Eq, Show)
|
} deriving (Eq, Show, Generic, JSON.ToJSON)
|
||||||
|
|
||||||
instance Ord PgVersion where
|
instance Ord PgVersion where
|
||||||
(PgVersion v1 _) `compare` (PgVersion v2 _) = v1 `compare` v2
|
(PgVersion v1 _) `compare` (PgVersion v2 _) = v1 `compare` v2
|
||||||
|
|||||||
Reference in New Issue
Block a user