content: -- |
  -- Module      : Database.Relational.Internal.Config
  -- Copyright   : 2017-2019 Kei Hibino
  -- License     : BSD3
  --
  -- Maintainer  : ex8k.hibino@gmail.com
  -- Stability   : experimental
  -- Portability : unknown
  --
  -- This module defines configuration datatype used in query products.
  module Database.Relational.Internal.Config (
    Config,
  
    defaultConfig,
  
    {- field labels of 'Config' type.
       To avoid haddock bug ( https://github.com/haskell/haddock/issues/456 ),
       they are not listed in Config ( ... ). -}
    productUnitSupport,
    chunksInsertSize,
    schemaNameMode,
    normalizedTableName,
    addQueryTableAliasAS,
    addModifyTableAliasAS,
    enableWarning,
    verboseAsCompilerWarning,
    disableOverloadedProjection,
    disableSpecializedProjection,
    identifierQuotation,
    nameConfig,
  
    NameConfig,
    defaultNameConfig,
  
    {- field labels of 'NameConfig' type.
       To avoid haddock bug ( https://github.com/haskell/haddock/issues/456 ),
       they are not listed in NameConfig ( ... ). -}
    recordConfig,
    relationVarName,
  
    ProductUnitSupport (..), SchemaNameMode (..), IdentifierQuotation (..),
    ) where
  
  import Language.Haskell.TH.Name.CamelCase (VarName, varCamelcaseName)
  import qualified Database.Record.TH as RecordTH
  
  
  -- | 'NameConfig' type to customize names of expanded templates.
  data NameConfig =
    NameConfig
    { recordConfig       ::  RecordTH.NameConfig
    -- ^ Configurations related to the names of generated record types
    --   and their field labels.
    , relationVarName    ::  String -> String -> VarName
    -- ^ Function to build the name of 'Database.Relational.Monad.BaseType.Relation' representing the table.
    --   The first argument is the scheme name, and second argument is the table name.
    }
  
  instance Show NameConfig where
    show = const "<NameConfig>"
  
  -- | Default implementation of 'NameConfig' type.
  defaultNameConfig :: NameConfig
  defaultNameConfig =
    NameConfig
    { recordConfig    = RecordTH.defaultNameConfig
    , relationVarName = const varCamelcaseName
    }
  
  -- | Unit of product is supported or not.
  data ProductUnitSupport = PUSupported | PUNotSupported  deriving Show
  
  -- | Schema name qualify mode in SQL string.
  data SchemaNameMode
    = SchemaQualified     -- ^ Schema qualified table name in SQL string
    | SchemaNotQualified  -- ^ Not qualified table name in SQL string
    deriving (Eq, Show)
  
  -- | Configuration for quotation of identifiers of SQL.
  data IdentifierQuotation = NoQuotation | Quotation Char deriving Show
  
  -- | Configuration type.
  data Config =
    Config
    { productUnitSupport           ::  !ProductUnitSupport
    -- ^ No FROM clause (corresponding the unit of JOIN) is allowed or not.
    , chunksInsertSize             ::  !Int
    -- ^ Threshold count of placeholders in the insert statement with multi-values.
    , schemaNameMode               ::  !SchemaNameMode
    -- ^ 'SchemaNameMode' configuration
    , normalizedTableName          ::  !Bool
    -- ^ If True, schema names become uppercase, and table names become lowercase.
    , addQueryTableAliasAS         ::  !Bool
    -- ^ If True, AS keyword is not skipped but added in table-alias of SELECT statement or correlate SELECT clause.
    , addModifyTableAliasAS        ::  !Bool
    -- ^ If True, AS keyword is not skipped but added in target-table-alias of UPDATE and DELETE statement.
    , enableWarning                ::  !Bool
    -- ^ If True, print warning messages in macros of relational-record.
    , verboseAsCompilerWarning     ::  !Bool
    -- ^ If True, more detailed logs are printed when generating record types from schema.
    , disableOverloadedProjection  ::  !Bool
    -- ^ If True, instance of 'Database.Relational.OverloadedProjection.HasProjection' for each column is NOT generated.
    , disableSpecializedProjection ::  !Bool
    -- ^ If True, 'Database.Relational.Pi.Pi' for each column is NOT generated.
    , identifierQuotation          ::  !IdentifierQuotation
    -- ^ 'IdentifierQuotation' configuration
    , nameConfig                   ::  !NameConfig
    -- ^ 'NameConfig' configuration
    } deriving Show
  
  -- | Default configuration of 'Config'.
  --   To change some behaviour of relational-query,
  --   use record update syntax:
  --
  -- @
  --   defaultConfig
  --     { productUnitSupport            =  'PUSupported'
  --     , chunksInsertSize              =  256
  --     , schemaNameMode                =  'SchemaQualified'
  --     , normalizedTableName           =  True
  --     , addQueryTableAliasAS          =  False
  --     , addModifyTableAliasAS         =  False
  --     , enableWarning                 =  True
  --     , verboseAsCompilerWarning      =  False
  --     , disableOverloadedProjection   =  False
  --     , disableSpecializedProjection  =  False
  --     , identifierQuotation           =  'NoQuotation'
  --     , nameConfig                    =
  --        defaultNameConfig
  --        { recordConfig     =  'RecordTH.defaultNameConfig'
  --        , relationVarName  =  \\schema table -> 'varCamelcaseName' $ table ++ "_" ++ schema
  --        -- ^ append the table name after the schema name. e.g. "schemaTable"
  --        }
  --     }
  -- @
  defaultConfig :: Config
  defaultConfig =
    Config { productUnitSupport            =  PUSupported
           , chunksInsertSize              =  256
           , schemaNameMode                =  SchemaQualified
           , normalizedTableName           =  True
           , addQueryTableAliasAS          =  False
           , addModifyTableAliasAS         =  False
           , enableWarning                 =  True
           , verboseAsCompilerWarning      =  False
           , disableOverloadedProjection   =  False
           , disableSpecializedProjection  =  False
           , identifierQuotation           =  NoQuotation
           , nameConfig                    =  defaultNameConfig
           }
  