cabal-version: 3.12 name: pg-schema version: 0.8.1.0 category: Database author: Dmitry Olshansky maintainer: olshanskydr@gmail.com copyright: Dmitry Olshansky license: BSD-3-Clause license-file: LICENSE build-type: Simple tested-with: GHC ==9.10.3 , GHC ==9.12.4 , GHC ==9.14.1 synopsis: Type-level definition of database schema and safe DML for PostgreSQL. description: == Schema definition Use `updateSchemaFile` function from "PgSchema.Generation" module to generate type-level definition of database schema. You can make several schemas with any parts of your database. Usually you make executable which imports this module and run it to generate schema definition. You can run it on CI to check if schema definition is up to date. == Safe DML for PostgreSQL Use "PgSchema.DML" module to describe and generate (in runtime) safe DML for PostgreSQL. All operations are statically checked and you can't write invalid SQL. With @pg-schema@ you can select or insert/upsert data into tree-like ADT in one request. === Example Let's say - we have a database with tables: "orders", "order_positions", "articles". - There are articles with ids 41 and 42. - We have generated `MySch` schema with `updateSchemaFile` function from "PgSchema.Generation" module. Then we can write a function to insert an order with order positions. And select orders with order positions and articles in one request using some conditions for orders and order positions that return in order. Note that all table names, field names and foreign key constraint names are checked in compile time! @ data Order = Order { num :: Text, createdAt :: Day, items :: [OrdPos] } deriving Generic data OrdPos = OrdPos { id :: Int32, num :: Int32, article :: Article, price :: Double } deriving Generic data Article = Article { id :: Int32, name :: Text } deriving Generic type MyAnn tabName = 'Ann CamelToSnake MySch 5 ("dbSchema" ->> tabName) ... do -- insert an order with order positions void $ insertJSON_ (MyAnn "orders") conn [ "num" =: "num1" :. "ord__ord_pos" =: [ "num" =: 1 :. "articleId" =: 42 :. "price" =: 10 , "num" =: 2 :. "articleId" =: 41 :. "price" =: 15 ] ] -- select orders (xs :: [Order]) <- selectSch (MyAnn "orders") conn $ qRoot do qWhere $ "created_at" >? someDay &&& pchild "ord__ord_pos" defTabParam (pparent "ord_pos__article" $ "name" ~~? "%pencil%") qOrderBy [descf "created_at", descf "num"] qPath "ord__ord_pos" do qWhere $ pparent "ord_pos__article" $ "name" ~~? "%pencil%" qOrderBy [ascf "num"] qLimit 20 @ === Structure of modules * "PgSchema.Generation" - module with generation functions. Usually you make executable which generates schema definition using this module. * "PgSchema.DML" - module with DML functions. Import this module into your application and use it to generate safe DML for PostgreSQL. * "PgSchema.Import" - generated schema module imports this module. homepage: https://github.com/odr/pg-schema/tree/master/pg-schema#readme bug-reports: https://github.com/odr/pg-schema/issues extra-doc-files: ChangeLog.md README.md source-repository head type: git location: https://github.com/odr/pg-schema flag time description: Make CanConvert1 instances for Time types manual: True default: True flag uuid description: Make CanConvert1 instances for UUID type manual: True default: True flag case-insensitive description: Make CanConvert1 instances for CaseInsensitive type manual: True default: True flag arbitrary description: Make Arbitrary instances for all types (Enums, PgTag) manual: True default: False flag debug description: Trace queries manual: True default: False flag flat description: Make Flat instances for all types (Enums, PgTag) manual: True default: False flag hashable description: Make Hashable instances for all types (Enums, PgTag) manual: True default: False common shared build-depends: base >= 4.20 && < 5 , bytestring >= 0.10 && < 0.13 default-language: GHC2021 default-extensions: AllowAmbiguousTypes BlockArguments ExplicitNamespaces DataKinds -- ^^^ added in GHC2024 DerivingStrategies FunctionalDependencies LambdaCase -- ^^^ added in GHC2024 MultiWayIf OverloadedRecordDot OverloadedStrings PatternSynonyms RecordWildCards RequiredTypeArguments -- TemplateHaskell TypeAbstractions TypeFamilies ViewPatterns ghc-options: -Wall -Wunused-packages library import: shared exposed-modules: -- PgSchema PgSchema.DML PgSchema.Generation PgSchema.Import PgSchema.Schema.Catalog PgSchema.Schema.Info PgSchema.GenDot other-modules: PgSchema.Ann PgSchema.DML.Delete PgSchema.DML.Insert PgSchema.DML.InsertJSON PgSchema.DML.Insert.Types PgSchema.DML.KeyedWrite PgSchema.DML.UpsertByKey PgSchema.DML.Select PgSchema.DML.Select.Types PgSchema.DML.Update PgSchema.Schema PgSchema.Types PgSchema.Utils.CamelToSnake PgSchema.Utils.Instances PgSchema.Utils.Internal PgSchema.Utils.TF PgSchema.Utils.ShowType -- Paths_pg_schema PackageInfo_pg_schema autogen-modules: Paths_pg_schema PackageInfo_pg_schema hs-source-dirs: src build-depends: aeson >= 2.0 && < 2.3 , containers >= 0.7 && < 0.9 , directory >= 1.3 && < 1.5 , exceptions >= 0.9 && < 0.11 , mtl >= 2.0 && < 2.4 , postgresql-simple >= 0.6 && < 0.8 , postgresql-libpq >= 0.11 && < 0.12 , scientific >= 0.2 && < 0.4 , singletons >= 3.0.3 && < 3.1 , singletons-th >= 3.4 && < 3.6 , text >= 2.0 && < 2.2 if flag(time) build-depends: time >= 1.12 && < 2 cpp-options: -DMK_TIME if flag(uuid) build-depends: uuid-types >= 1.0 && < 1.1 cpp-options: -DMK_UUID if flag(case-insensitive) build-depends: case-insensitive >= 1.0 && < 1.3 cpp-options: -DMK_CASE_INSENSITIVE if flag(flat) build-depends: flat >= 0.6 && < 0.7 cpp-options: -DMK_FLAT if flag(arbitrary) build-depends: QuickCheck >= 2.14.0 && < 2.18 cpp-options: -DMK_ARBITRARY if flag(hashable) build-depends: hashable >= 1.5.1 && < 1.6 cpp-options: -DMK_HASHABLE if flag(debug) cpp-options: -DDEBUG test-suite json-spec import: shared type: exitcode-stdio-1.0 main-is: json-spec.hs other-modules: PgTagJsonSpec Paths_pg_schema PackageInfo_pg_schema autogen-modules: Paths_pg_schema PackageInfo_pg_schema hs-source-dirs: test build-depends: aeson , pg-schema , text test-suite test-gen import: shared type: exitcode-stdio-1.0 hs-source-dirs: test-gen main-is: Main.hs other-modules: -- Paths and PackageInfo Paths_pg_schema PackageInfo_pg_schema autogen-modules: Paths_pg_schema PackageInfo_pg_schema build-depends: pg-schema , postgresql-simple >= 0.6 && < 0.8 test-suite test-pgs import: shared type: exitcode-stdio-1.0 hs-source-dirs: test-pgs main-is: Main.hs other-modules: Sch Tests.Aggregates Tests.BaseConverts Tests.Conditions Tests.Hierarchy Tests.KeyedDML Tests.InsertJSONTransaction Tests.UpsertUniqueKey Tests.Path Utils -- Paths and PackageInfo Paths_pg_schema PackageInfo_pg_schema autogen-modules: Paths_pg_schema PackageInfo_pg_schema build-depends: aeson, case-insensitive, hedgehog >= 1.1, pg-schema, postgresql-simple >= 0.6 && < 0.8, resource-pool, scientific, tasty >= 1.4, tasty-hedgehog >= 1.2, text, time, uuid-types, vector, -- they can be excluded by flags deepseq --------------- if flag(hashable) build-depends: hashable >= 1.5.1 && < 1.6 cpp-options: -DMK_HASHABLE