content: 
  
  New approach to dialacts, more rule driven so all the options for a
  dialect can appear here.
  
  It would be nice to make the dialects completely rule driven, but I
  think this is much less maintainable than making them mainly rule
  driven (primarily via the catalogs), but with some special cases
  scattered in the source code.
  
  The dialect contains:
  the name of the dialect
  some parsing options about what syntax is supported
  some options about typechecking support
  
  flags to control the details of the dialect (for instance, some
  dialects have additional options to specify which kinds of string
  literal escapes are valid, so this is like subdialect
  
  stuff about types:
  
  canonical names of types with multiple names (these are only the
  built in types, user/catalog driven type aliases are not covered here)
  the built in text types
  the built in datetime types
  
  default catalog for this dialect
  
  
  then supplied with hssqlppp are:
  base dialect with minimal stuff in it
  ansi2011 dialect
  recent-ish postgresql dialect
  recent-ish sql server dialect
  recent-ish oracle dialect
  
  the idea is that if you have one of these dialects, you can start here
  then add your own catalog entries and use it as is. If your dialect is
  not here, and is it similar enough to an existing dialect, you can
  take that dialect and
      a) modify some of the dialect options
      b) modify the default catalog
      and you will get something useful
  
  if the dialect is too different, then you will have to edit the
  hssqlppp source.
  
  > {-# LANGUAGE DeriveDataTypeable #-}
  > module Database.HsSqlPpp.Internals.Dialect
  >     (Dialect(..)
  >     ,SyntaxFlavour(..)
  >     ,canonicalizeTypeName
  >     ,ansiTypeNameToDialect) where
  
  > import Database.HsSqlPpp.Internals.Catalog.CatalogTypes
  > import Data.Data
  > import Data.Text (Text)
  > import qualified Data.Text as T
  > import Data.List (find)
  > import Data.Char (toLower)
  
  > data Dialect = Dialect
  >      {diName :: String
  
  represent the syntax variations with a crude enum. Later, can make
  this more rule driven.
  
  >      ,diSyntaxFlavour :: SyntaxFlavour
  
  map from alternative names to the canonical name of built in
  types. This is used e.g. because in ansi the canonical name of boolean
  type is 'boolean', and in postgresql the canonical name of this type
  is 'bool'.
  These should all be in lower case
  
  >      ,diCanonicalTypeNames :: [(Text,[Text])]
  
  the names of the built in text types. This is used to help type check
  built in functions like substring?
  
  >      ,diTextTypes :: [Text] -- names of the text types (canonical names must be used)
  
  used to typecheck things like extract
  
  todo: create a single function which takes the ansi name of a type and
  returns the dialect specific name (as a maybe) - then don't have to
  have a huge number of functions here.
  
  Also, these functions should be -TypeName not -Type.
  
  >      ,diDatetimeTypes :: [Text]
  >      ,diNumberTypes :: [Text] -- names of the number types (canonical names must be used)
  >      -- this is a map from the canonical ansi name (in hssqlppp)
  >      -- to the canonical name in the dialect
  >      -- if there is no entry, then it means that type isn't
  >      -- supported in this dialect
  
  todo: make a list of exactly what type names are needed in the type
  checker and why. This should only be used for the type checker
  internally, and not anywhere else. Should do the same for the
  other fields above
  
  >      ,namesForAnsiTypes :: [(Text,Text)]
  
  A small issue with having the default catalog like this is that we can
  make a programming error where we have a function which takes the
  dialect and a catalog, and we use this default catalog instead of the
  supplied updated catalog.
  
  >      ,diDefaultCatalog :: Catalog
  >      } deriving (Eq,Show,Data,Typeable)
  
  > data SyntaxFlavour = Ansi | Postgres | SqlServer | Oracle
  >                      deriving (Eq,Show,Data,Typeable)
  
  > ansiTypeNameToDialect :: Dialect -> Text -> Maybe Text
  > ansiTypeNameToDialect d n = lookup n (namesForAnsiTypes d)
  
  > canonicalizeTypeName :: Dialect -> Text -> Text
  > canonicalizeTypeName d s =
  >     let m = diCanonicalTypeNames d
  >     in ct m s
  >   where
  >     hasType t p = let t' = T.map toLower t
  >                   in t' `elem` snd p
  >     ct m tn = maybe tn fst
  >               $ find (hasType tn) m
  
  TODO:
  modify the catalog:
    when adding a type flags to say:
      if this type is a text or datetime or number type
      if it is built in
      if it is undroppable
      if it has a list of builtin aliases
      what the ansi equivalent type name is
  
  this will get rid of most of the fields in the dialect and make it
  much easier to keep everything consistent and maintainable
  
  start adding flags for which bits of syntax to support instead of
  using the syntax flavour thing
  there will be flags like this for typechecking also
  
  support functions to help create minimal dialects
    e.g. take ansi, and safely remove a bunch of types and functions
  
  write the default catalogs and dialects all in one file
    (they are split into two at the moment)
  
  export the ansidialect every module that exposes something with a
  dialect (function or data type) - parse, pretty, lex, typecheck, etc.
  
  then you only need to import the dialects module to get the other
  dialects
  
  consider how the catalog in the dialect can help with parsing
  operators
  
  minimal dialects:
  mainly missing types then following through on implications:
  no text types
  only one text type covering char,varchar,nclob, etc.
  no numeric or decimal
  on decimal for all integers and precise decimals
  no date or time types
  
  
  Types:
  typeextra: needs fixing
  how to represent e.g. 'varchar' without precision
  
  invent some sort of concrete syntax (which is parseable) to
  represent implicit casts (cast implicit x as varchar)?
  