postgresql-types-algebra (empty) → 0.0.1
raw patch · 4 files changed
+309/−0 lines, 4 filesdep +attoparsecdep +basedep +bytestring
Dependencies added: attoparsec, base, bytestring, ptr-peeker, ptr-poker, tagged, text, text-builder
Files
- LICENSE +22/−0
- README.md +61/−0
- postgresql-types-algebra.cabal +109/−0
- src/library/PostgresqlTypes/Algebra.hs +117/−0
+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2025, Nikita Volkov++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,61 @@+# postgresql-types-algebra++[](https://hackage.haskell.org/package/postgresql-types-algebra)+[](https://nikita-volkov.github.io/postgresql-types-algebra/)++Core type classes and algebra for PostgreSQL type mappings, extracted from ["postgresql-types"](https://github.com/nikita-volkov/postgresql-types).++## Overview++This package provides the fundamental abstractions for mapping Haskell types to PostgreSQL types:++- **Type classes** defining the algebra for PostgreSQL type mappings+- **Error types** for decoding failures+- **Metadata support** for type names, OIDs, and parameters+- **No concrete implementations** - just the algebra++## Type Classes++### `IsScalar`++The core type class for types that map to PostgreSQL values:++```haskell+class IsScalar a where+ -- Type metadata+ typeName :: Tagged a Text+ baseOid :: Tagged a (Maybe Word32)+ arrayOid :: Tagged a (Maybe Word32)+ typeParams :: Tagged a [Text]+ typeSignature :: Tagged a Text+ + -- Binary format+ binaryEncoder :: a -> Write.Write+ binaryDecoder :: PtrPeeker.Variable (Either DecodingError a)+ + -- Textual format+ textualEncoder :: a -> TextBuilder.TextBuilder+ textualDecoder :: Attoparsec.Parser a+```++This class enables:+- **Binary encoding/decoding** using PostgreSQL's native binary format+- **Textual encoding/decoding** using PostgreSQL's text representation +- **Type metadata** including OIDs and type signatures for parameterized types+- **Round-trip fidelity** through all encoding combinations++## Use Cases++### For Library Authors++Use this package to:+- Define custom PostgreSQL type mappings compatible with the "postgresql-types" ecosystem+- Create adapter libraries for different PostgreSQL client libraries+- Build generic tools that work with any `IsScalar` instance++### For Application Developers++This package is typically used indirectly through:+- ["postgresql-types"](https://github.com/nikita-volkov/postgresql-types) - Concrete type implementations+- ["hasql-postgresql-types"](https://github.com/nikita-volkov/hasql-postgresql-types) - "hasql" integration+- ["postgresql-simple-postgresql-types"](https://github.com/nikita-volkov/postgresql-simple-postgresql-types) - "postgresql-simple" integration
+ postgresql-types-algebra.cabal view
@@ -0,0 +1,109 @@+cabal-version: 3.0+name: postgresql-types-algebra+version: 0.0.1+category: PostgreSQL, Codecs+synopsis: Type classes for PostgreSQL type mappings+description:+ Core type classes and algebra extracted from the postgresql-types library.++ Defines the fundamental abstractions for mapping Haskell types to PostgreSQL types,+ including binary and textual encoding/decoding, type metadata, and error handling.++ This package provides the type class algebra without concrete type implementations,+ making it suitable as a lightweight dependency for libraries that want to define+ their own PostgreSQL type mappings or work with the postgresql-types ecosystem.++homepage: https://github.com/nikita-volkov/postgresql-types-algebra+bug-reports: https://github.com/nikita-volkov/postgresql-types-algebra/issues+author: Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer: Nikita Volkov <nikita.y.volkov@mail.ru>+copyright: (c) 2025, Nikita Volkov+license: MIT+license-file: LICENSE+extra-doc-files:+ LICENSE+ README.md++source-repository head+ type: git+ location: https://github.com/nikita-volkov/postgresql-types-algebra++common base+ default-language: Haskell2010+ default-extensions:+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveTraversable+ DerivingStrategies+ DerivingVia+ DuplicateRecordFields+ EmptyDataDecls+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ LambdaCase+ LiberalTypeSynonyms+ MagicHash+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ NoImplicitPrelude+ NoMonomorphismRestriction+ NumericUnderscores+ OverloadedStrings+ ParallelListComp+ PatternGuards+ QuasiQuotes+ RankNTypes+ RecordWildCards+ ScopedTypeVariables+ StandaloneDeriving+ StrictData+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeOperators+ UnboxedTuples+ ViewPatterns++common executable+ import: base+ ghc-options:+ -O2+ -threaded+ -with-rtsopts=-N+ -rtsopts+ -funbox-strict-fields++common test+ import: base+ ghc-options:+ -threaded+ -with-rtsopts=-N++library+ import: base+ hs-source-dirs: src/library+ exposed-modules:+ PostgresqlTypes.Algebra++ build-depends:+ attoparsec >=0.14 && <0.19,+ base >=4.11 && <5,+ bytestring >=0.10 && <0.13,+ ptr-peeker ^>=0.1,+ ptr-poker ^>=0.1.2.16,+ tagged ^>=0.8.9,+ text >=1.2 && <3,+ text-builder ^>=1.0.0.4,
+ src/library/PostgresqlTypes/Algebra.hs view
@@ -0,0 +1,117 @@+module PostgresqlTypes.Algebra where++import qualified Data.Attoparsec.Text as Attoparsec+import Data.ByteString (ByteString)+import Data.Tagged (Tagged (..), untag)+import Data.Text (Text)+import Data.Word (Word32)+import qualified PtrPeeker+import qualified PtrPoker.Write as Write+import TextBuilder (TextBuilder)+import qualified TextBuilder+import Prelude++-- | Evidence that a type maps to a PostgreSQL scalar value.+class IsScalar a where+ -- | PostgreSQL schema name, if applicable.+ schemaName :: Tagged a (Maybe Text)++ -- | PostgreSQL type name.+ typeName :: Tagged a Text++ -- | PostgreSQL type OID, if known at compile time.+ baseOid :: Tagged a (Maybe Word32)+ baseOid = Tagged Nothing++ -- | PostgreSQL array type OID, if known at compile time.+ arrayOid :: Tagged a (Maybe Word32)+ arrayOid = Tagged Nothing++ -- | Static type parameters. E.g., the @n@ in @char(n)@.+ typeParams :: Tagged a [Text]+ typeParams = Tagged []++ -- | Get the PostgreSQL type signature for a given Haskell type.+ --+ -- In case of parameterized types, the type parameters are included in the signature.+ -- For example, for @'PostgresqlTypes.Types.Bpchar.Bpchar' 10@, the signature will be @bpchar(10)@.+ typeSignature :: Tagged a Text+ typeSignature =+ let params = untag (typeParams @a)+ name = untag (typeName @a)+ in Tagged+ if null params+ then name+ else+ TextBuilder.toText+ ( mconcat+ [ TextBuilder.text name,+ "(",+ TextBuilder.intercalateMap ", " TextBuilder.text params,+ ")"+ ]+ )++ -- | Encode the value in PostgreSQL binary format.+ binaryEncoder :: a -> Write.Write++ -- | Decode the value from PostgreSQL binary format.+ binaryDecoder :: PtrPeeker.Variable (Either DecodingError a)++ -- | Represent the value in PostgreSQL textual format.+ textualEncoder :: a -> TextBuilder.TextBuilder++ -- | Decode the value from PostgreSQL textual format.+ textualDecoder :: Attoparsec.Parser a++-- | Evidence that a type can be used as an element of a PostgreSQL range type.+class (IsScalar a, Ord a) => IsRangeElement a where+ -- | PostgreSQL range type name.+ rangeTypeName :: Tagged a Text++ -- | Statically known OID for the range type.+ rangeBaseOid :: Tagged a (Maybe Word32)++ -- | Statically known OID for the range array-type.+ rangeArrayOid :: Tagged a (Maybe Word32)++-- | Evidence that a type can be used as an element of a PostgreSQL multirange type.+class (IsRangeElement a) => IsMultirangeElement a where+ -- | PostgreSQL multirange type name.+ multirangeTypeName :: Tagged a Text++ -- | Statically known OID for the multirange type.+ multirangeBaseOid :: Tagged a (Maybe Word32)++ -- | Statically known OID for the multirange array-type.+ multirangeArrayOid :: Tagged a (Maybe Word32)++data DecodingError = DecodingError+ { location :: [Text],+ reason :: DecodingErrorReason+ }+ deriving stock (Show, Eq)++data DecodingErrorReason+ = ParsingDecodingErrorReason+ -- | Details.+ Text+ -- | Input.+ ByteString+ | UnexpectedValueDecodingErrorReason+ -- | Expected.+ Text+ -- | Actual.+ Text+ | -- | Unsupported server-side value.+ --+ -- Useful for defining decoders on a narrower type than the underlying PostgreSQL type.+ --+ -- This one does not signal a problem with the data itself, but rather that the data does not meet+ -- the additional constraints imposed by the refinement.+ UnsupportedValueDecodingErrorReason+ -- | Details.+ Text+ -- | Value.+ Text+ deriving stock (Show, Eq)