packages feed

HaskRel 0.1.0.1 → 0.1.0.2

raw patch · 7 files changed

+104/−121 lines, 7 files

Files

HaskRel.cabal view
@@ -1,6 +1,6 @@ name:                HaskRel -version:             0.1.0.1+version:             0.1.0.2  synopsis:            HaskRel, Haskell as a DBMS with support for the relational                      algebra@@ -25,76 +25,11 @@   of two relations results in a relation with a heading that is the setwise   union of the headings of the original relations).   .-  = Examples-  .-  The examples in this documentation are based on "the old warhorse" that is the-  suppliers-parts database (see [1] for more). This gives a body of relational-  expressions with known results to base examples upon. See also-  examples\/SuppliersPartsExamples.hs (not visible from this documentation) for-  Haskell versions of a selection of the Tutorial D expressions given as-  examples in chapters 6 and 7 of [1]. These can be run by starting-  examples\/suppliersPartsDB.sh and then running @snrt2ndExamples@. While most-  Tutorial D expressions translate fairly verbatim to Haskell there are a few-  where one must be a bit more explicit. While most Tutorial D expressions-  translate fairly verbatim to Haskell there are a few where Haskell is stricter-  than Tutorial D and one must be a bit more explicit.-  .-  $ is always used after `p`\/`rPrint` or `pt`\/`rPrintTyped` in the examples to-  keep them uniform (and so it kinda looks like a prompt), even when not-  required. The short forms `p` and `pt` are used whenever there isn't a-  conflict with other identifiers, whereas for the SuppliersPartsExample, which-  has a relvar "@p@", `rPrint` is used instead of `p` for presentation of-  relational objects without type information.-  .-  = Terminology-  .-  Since this builds on both Haskell and relational theory this documentation-  uses terms as they have been established in material related to-  either. Several terms of Haskell and HList have been redefined in terms of-  relational theory in this library, mostly to illustrate how terms and concepts-  have been mapped from the latter to the former. (I'm trying to keep this open-  to change later if it turns out to be an unhelpful crutch.)-  .-  The following table gives a quick overview of either terms or concepts as-  found in Haskell, the relational model (as presented in [1]), HaskRel and SQL,-  and how they are mapped from the second to the first:-  .-  @-  ┌───────────────────────────┬────────────────────┬────────────┬────────────────────────────────────────────────┐-  │ haskell                   │ relModel           │ haskRel    │ sql                                            │-  ╞═══════════════════════════╪════════════════════╪════════════╪════════════════════════════════════════════════╡-  │ <https://hackage.haskell.org/package/tagged/docs/Data-Tagged.html Data.Tagged.Tagged>        │ attribute          │ Attr       │ field, column                                  │-  │ <https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html Data.HList.Record.Record>  │ tuple              │ RTuple     │ row                                            │-  │ ( <https://hackage.haskell.org/package/containers/docs/Data-Set.html Set> (<https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html Record> a) )        │ relation           │ Relation a │ table                                          │-  │ <https://hackage.haskell.org/package/filepath/docs/System-FilePath.html FilePath> (<https://hackage.haskell.org/package/containers/docs/Data-Set.html Set> (<https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html Record> a)) │ relvar             │ Relvar a   │ table                                          │-  │ <https://hackage.haskell.org/package/HList/docs/Data-HList-FakePrelude.html#t:Label Data.HList.Record.Label>   │ attribute name     │ Label      │ field name, column name                        │-  │ <https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html#t:Labels Data.HList.Record.Labels>  │ attribute name set │ Labels     │ list of field/column names                     │-  │ function, operator        │ operator           │ function   │ operator, function, procedure, routine, method │-  └───────────────────────────┴────────────────────┴────────────┴────────────────────────────────────────────────┘-  @-  .-  Found in "example\/Terminology.hs". Note that this is just an overview, study-  of [1] or [2], Haskell itself, HList and HaskRel is required to see how terms-  and concepts correlate.-  .-  The term \"RTuple\", or "r-tuple", is chosen to simultaneously distinguish the-  concept from Haskell tuples while relating it to tuples of the relational-  model. For the type of either "Record a" or "Set ( Record a )" in Haskell the-  term "heading" is used in relational theory, and "row type" or "composite-  type" in SQL. In relational theory the term "scalar" is used to refer to data-  types that are neither tuples nor relations, which corresponds to everything-  but "Record a" or "Set ( Record a )" in Haskell. Note also that HaskRel /does/-  use the term "table", but then only in the sense of "presentation of a-  relation value" (see above).-  .   == The HaskRel library   .   Not all modules of this library are relevant to gain an understanding of how   it functions, the next part to go to at this point is-  "Database.HaskRel.RDBMS", and the modules it reexports.-  .-  [1] <http://shop.oreilly.com/product/0636920022879.do SQL and Relational Theory, 2nd ed. (2011), C.J. Date>-  [2] <http://www.dcs.warwick.ac.uk/~hugh/TTM/TTM-2013-02-07.pdf The Third Manifesto, C. J. Date and Hugh Darwen, February 7th, 2013>+  "Database.HaskRel.RDBMS", and the modules it reexports. See also README.md.  license:             GPL-2 
README.md view
@@ -7,13 +7,13 @@ management that Haskell can accommodate, thus enabling Haskell (or more precisely GHC) in its own right as a DBMS with first-class support for those parts of the relational model. It does not qualify as a proper RDBMS since it-as-is only defines the relational algebra, relational variables and relational-assignment. It does not define the relational calculus, views, constraints and-transactions (beyond the fundamental requirement that the tuples of relations-are to be unique), certain operators like relation valued aggregate operators,-nor a few minor or even deprecated operators such as DIVIDE. The implemented-parts are decently complete even if there are major implementation shortcomings-that prevent this from being practically usable as an actual DBMS.+as-is only defines the relational algebra, base relational variables and+relational assignment. It does not define the relational calculus, views,+constraints and transactions (beyond the fundamental requirement that the tuples+of relations are to be unique), certain operators like relation valued aggregate+operators, nor a few minor or even deprecated operators such as DIVIDE. The+implemented parts are decently complete even if there are major implementation+shortcomings that prevent this from being practically usable as an actual DBMS.  I refer to it as _first-class_ since the types of the relational model are first-class types to Haskell, and the Haskell type system is able to induce the@@ -38,7 +38,7 @@ which has been the principal guide in this endeavor (I have plenty of SQL in my background so a book on SQL and the relational model has been a good introduction to the latter). See also-[The Third Manifesto, TTM](http://www.dcs.warwick.ac.uk/~hugh/TTM/TTM-2013-02-07.pdf),+[The Third Manifesto (TTM)](http://www.dcs.warwick.ac.uk/~hugh/TTM/TTM-2013-02-07.pdf), and the additional material on <http://www.thethirdmanifesto.com/> (this might be better to start with for those mathematically inclined but not steeped in SQL). Regarding The Third Manifesto it is important to note that all parts of@@ -122,8 +122,8 @@ particularly [`Database.HaskRel.Relational.Expression`](http://hackage.haskell.org/package/HaskRel/docs/Database-HaskRel-Relational-Expression.html), which "pulls together" both the algebra and assignment functions and generalizes-them to operate as they should in a DBMS (with caveats), on both variables and-values.+them to operate as they should in a DBMS (with caveats), on both base variables+and values.  Alternatively, `cabal repl` will start a GHCi session with the required modules loaded, although one will have to either load a file with definitions, or define
examples/MiniDB.hs view
@@ -1,19 +1,13 @@-{-# LANGUAGE DataKinds, TemplateHaskell #-}- {- | An even smaller DB for minimal examples -} module MiniDB where  import Data.HList.CommonMain import Database.HaskRel.RDBMS -makeLabels6 ["sno","sName","status","city", "pno", "qty"]--dbPath = "./"--sp :: Relvar '[Attr "sno"    String,-               Attr "pno"    String,-               Attr "qty"    Integer]-sp  = Relvar ( dbPath ++ "SP.rv" )+sp :: Relvar '[Attr "sno" String,+               Attr "pno" String,+               Attr "qty" Integer]+sp  = Relvar "SP.rv"  {- 
examples/SuppliersPartsDB/Definition.hs view
@@ -28,17 +28,6 @@ Which is what one must append to "let " to do the same in GHCi. -} -{- Tagged value/attribute constructors. These are convenient to have since the-label names collide with the label functions when punning, which is a particular-nuisance when using 'extend' to alter an attribute:--}-_sno a = sno .=. a :: SNO-_sName a = sName .=. a :: SName-_status a = status .=. a :: Status-_city a = city .=. a :: City--- type PNO    = Attr "pno"    String type PName  = Attr "pName"  String type Color  = Attr "color"  String@@ -46,17 +35,10 @@  makeLabels6 ["pno","pName","color","weight"] -_pno a = pno .=. a :: PNO-_pName a = pName .=. a :: PName-_color a = color .=. a :: Color-_weight a = weight .=. a :: Weight - type QTY    = Attr "qty"    Integer  makeLabels6 ["qty"]--_qty a = qty .=. a :: QTY   -- Types. Header types in relational theory, of either relations or tuples.
examples/SuppliersPartsExample.hs view
@@ -22,7 +22,7 @@ -- directly, instead of "relation"/"relation'" import Data.Set ( Set, fromList ) -makeLabels6 ["pnoRel","pq","sn","pn","x","y","nc","nw","qtys"]+makeLabels6 ["pnoRel","pq","sn","pn","x","y","nc","nw"]  recreate = do   putStrLn $ "\nRecreating database at "++ dbPath@@ -51,9 +51,9 @@                rTuple (sno .=. "S4", pno .=. "P4"),                rTuple (sno .=. "S4", pno .=. "P5")] -r4 = relation [rTuple (sno .=. "S2", pnoRel .=. relation [pno .=. "P1" .*. emptyRecord, pno .=. "P2"  .*. emptyRecord]),-               rTuple (sno .=. "S3", pnoRel .=. relation [pno .=. "P2" .*. emptyRecord]),-               rTuple (sno .=. "S4", pnoRel .=. relation [pno .=. "P2" .*. emptyRecord, pno .=. "P4" .*. emptyRecord, pno .=. "P5" .*. emptyRecord])]+r4 = relation [rTuple (sno .=. "S2", pnoRel .=. relation [rTuple (pno .=. "P1"), rTuple (pno .=. "P2")]),+               rTuple (sno .=. "S3", pnoRel .=. relation [rTuple (pno .=. "P2")]),+               rTuple (sno .=. "S4", pnoRel .=. relation [rTuple (pno .=. "P2"), rTuple (pno .=. "P4"), rTuple (pno .=. "P5")])]   spq = Relvar "SPQ.rv"@@ -135,11 +135,11 @@   putStrLn "\n133"   rPrint$ s `matching` sp   rPrint$ s `notMatching` sp-  rPrint$ extend p (\[pun|weight|] -> (Label::Label "gmwt") .=. weight * 454 .*. emptyRecord)+  rPrint$ extend p (\[pun|weight|] -> case weight * 454 of gmwt -> [pun|gmwt|]) --   putStrLn "\n134"   rPrint$ ( ( extend p-              (\[pun|weight|] -> (Label::Label "gmwt") .=. weight * 454 .*. emptyRecord))+              (\[pun|weight|] -> case weight * 454 of gmwt -> [pun|gmwt|]))             `restrict` (\[pun|gmwt|] -> gmwt > 7000) )               `project` (Proxy :: Labels '["pno", "gmwt"]) --@@ -175,12 +175,11 @@    putStrLn "\n137" -- Note how the variable sno overrides the defined label sno, which is worked--- around by using the constructor _sno instead. Another alternative would be--- (Label::Label "sno") .=. sno.+-- around by using (Label::Label "sno") .=. sno.   rPrint$ do spx <- readRelvar sp              px <- readRelvar p              s `restrict` (\[pun|sno|] ->-                             ( ( spx `matching` ( relation [rTuple (_sno sno)] ) )+                             ( ( spx `matching` ( relation [rTuple ((Label::Label "sno") .=. sno)] ) )                                `project` (rHdr (pno)) )                              == px `project` (rHdr (pno)))   -- Skipping pp. 138-139 and DIVIDE since it's not implemented in HaskRel, see@@ -263,7 +262,7 @@ --   putStrLn "\n154 (using pt instead of rPrint here to show the attribute types)"   pt$ do spx <- readRelvar sp-         extend s (\( image -> ii ) -> pq .=. (ii spx) .*. emptyRecord)+         extend s (\( image -> ii ) -> case (ii spx) of pq -> [pun|pq|]) --   putStrLn "\n155"   rPrint$ ( spq `ungroup` pq ) `restrict` (\[pun|pno|] -> pno == "P2") `project` (rHdr (sno))@@ -325,7 +324,8 @@   do spx <- readRelvar sp      update s             (\( image -> ii ) -> ( sum $ agg qty (ii spx) ) < 1000)-            (\[pun|status|] -> _status (floor $ 0.5 * toRational status) .*. emptyRecord)+            (\[pun|status|] -> case floor $ 0.5 * toRational status+                                 of status -> [pun|status|])   putStrLn "Post update"   rPrint$ s 
src/Database/HaskRel/RDBMS.hs view
@@ -12,10 +12,78 @@ Exports the pertinent parts of HaskRel building on HList records. This gives most features of the relational algebra, relation variable support, HList CommonMain, as well as certain non-relational features such as ordering.++/This section below belongs in the package description, but Hackage doesn't/+/format the package description in a satisfactory manner/.++= Examples++The examples in this documentation are based on "the old warhorse" that is the+suppliers-parts database (see [1] for more). This gives a body of relational+expressions with known results to base examples upon. See also+examples\/SuppliersPartsExamples.hs (not visible from this documentation) for+Haskell versions of a selection of the Tutorial D expressions given as examples+in chapters 6 and 7 of [1]. These can be run by starting+examples\/suppliersPartsDB.sh and then running @snrt2ndExamples@. While most+Tutorial D expressions translate fairly verbatim to Haskell there are a few+where one must be a bit more explicit. While most Tutorial D expressions+translate fairly verbatim to Haskell there are a few where Haskell is stricter+than Tutorial D and one must be a bit more explicit.++$ is always used after `p`\/`rPrint` or `pt`\/`rPrintTyped` in the examples to+keep them uniform (and so it kinda looks like a prompt), even when not+required. The short forms `p` and `pt` are used whenever there isn't a conflict+with other identifiers, whereas for the SuppliersPartsExample, which has a+relvar "@p@", `rPrint` is used instead of `p` for presentation of relational+objects without type information.++= Terminology++Since this builds on both Haskell and relational theory this documentation uses+terms as they have been established in material related to either. Several terms+of Haskell and HList have been redefined in terms of relational theory in this+library, mostly to illustrate how terms and concepts have been mapped from the+latter to the former. (I'm trying to keep this open to change later if it turns+out to be an unhelpful crutch.)++The following table gives a quick overview of either terms or concepts as found+in Haskell, the relational model (as presented in [1]), HaskRel and SQL, and how+they are mapped from the second to the first:++@+┌───────────────────────────┬────────────────────┬────────────┬────────────────────────────────────────────────┐+│ haskell                   │ relModel           │ haskRel    │ sql                                            │+╞═══════════════════════════╪════════════════════╪════════════╪════════════════════════════════════════════════╡+│ <https://hackage.haskell.org/package/tagged/docs/Data-Tagged.html Data.Tagged.Tagged>        │ attribute          │ Attr       │ field, column                                  │+│ <https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html Data.HList.Record.Record>  │ tuple              │ RTuple     │ row                                            │+│ ( <https://hackage.haskell.org/package/containers/docs/Data-Set.html Set> (<https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html Record> a) )        │ relation           │ Relation a │ table                                          │+│ <https://hackage.haskell.org/package/filepath/docs/System-FilePath.html FilePath> (<https://hackage.haskell.org/package/containers/docs/Data-Set.html Set> (<https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html Record> a)) │ relvar             │ Relvar a   │ table                                          │+│ <https://hackage.haskell.org/package/HList/docs/Data-HList-FakePrelude.html#t:Label Data.HList.Record.Label>   │ attribute name     │ Label      │ field name, column name                        │+│ <https://hackage.haskell.org/package/HList/docs/Data-HList-Record.html#t:Labels Data.HList.Record.Labels>  │ attribute name set │ Labels     │ list of field/column names                     │+│ function, operator        │ operator           │ function   │ operator, function, procedure, routine, method │+└───────────────────────────┴────────────────────┴────────────┴────────────────────────────────────────────────┘+@++Found in "example\/Terminology.hs". Note that this is just an overview, study of+[1] or [2], Haskell itself, HList and HaskRel is required to see how terms and+concepts correlate.++The term \"RTuple\", or "r-tuple", is chosen to simultaneously distinguish the+concept from Haskell tuples while relating it to tuples of the relational+model. For the type of either "Record a" or "Set ( Record a )" in Haskell the+term "heading" is used in relational theory, and "row type" or "composite type"+in SQL. In relational theory the term "scalar" is used to refer to data types+that are neither tuples nor relations, which corresponds to everything but+"Record a" or "Set ( Record a )" in Haskell. Note also that HaskRel /does/ use+the term "table", but then only in the sense of "presentation of a relation+value" (see above).++[1] <http://shop.oreilly.com/product/0636920022879.do SQL and Relational Theory, 2nd ed. (2011), C.J. Date>+[2] <http://www.dcs.warwick.ac.uk/~hugh/TTM/TTM-2013-02-07.pdf The Third Manifesto, C. J. Date and Hugh Darwen, February 7th, 2013> -}  {- TODO: Should call this something else than RDBMS seeing as it's so far just a-DBMS + relational algebra+DBMS + relational algebra + base relvars -} module Database.HaskRel.RDBMS (   module Data.HList.CommonMain,
src/Database/HaskRel/Relational/Assignment.hs view
@@ -204,7 +204,7 @@  {-| Updates tuples of a relvar that match the given predicate. As SQL UPDATE. ->>> update sp (\ [pun|pno|] -> pno == "P2" || pno == "P3" ) (\ [pun|qty|] -> _qty ( qty - 25 ) .*. emptyRecord)+>>> update sp (\ [pun|pno|] -> pno == "P2" || pno == "P3" ) (\ [pun|qty|] -> case qty - 25 of qty -> [pun|qty|] ) Updated 5 of 12 tuples in SuppliersPartsDB/SP.rv *SuppliersPartsExample> rPrint$ sp ┌─────┬─────┬─────┐@@ -222,7 +222,7 @@ Value assigned to SuppliersPartsDB/SP.rv >>> count sp 12->>> update sp (\[pun|pno|] -> pno == "P1" || pno == "P2" || pno == "P3") (\_ -> _pno "P1" .*. _qty 50 .*. emptyRecord)+>>> update sp (\[pun|pno|] -> pno == "P1" || pno == "P2" || pno == "P3") (\_ -> case ("P1", 50) of (pno, qty) -> [pun|pno qty|]) Updated 7 of 12 tuples in SuppliersPartsDB/SP.rv >>> count sp 9@@ -230,10 +230,14 @@ -- TODO: Fix update count message to reflect the situation in the last example -- above, although this is tricky as this is most likely something that belongs -- naturally in the set level functions. Note however that it is not feasable to--- give update counts at all in RDBSMs, as keeping exact track of the+-- give update counts at all in RDBMSs, as keeping exact track of the -- cardinality of relvars constitutes an overhead that is in many cases -- unacceptable, and doesn't provide information that is as useful as a naïve -- mind might think anyhow.+-- Long term TODO: When constraints are introduced it would be desirable to+-- define a function that requires that the attributes not updated must form a+-- superkey, so that you don't accidentally reduce a relvar when you don't+-- intend to. update   :: (Ord (HList a), Read (HList (RecordValuesR a)),       Show (HList (RecordValuesR a)), RecordValues a,@@ -278,7 +282,7 @@ optional clauses isn't idiomatic Haskell, hence this separate updateAll function. ->>> updateAll sp (\ [pun|qty pno|] -> _qty ( qty - 25 ) .*. _pno ( pno ++ "X" ) .*. emptyRecord)+>>> updateAll sp (\ [pun|qty pno|] -> case (qty - 25, pno ++ "X") of (qty, pno) -> [pun|qty pno|]) Updated 12 tuples in SuppliersPartsDB/SP.rv *SuppliersPartsExample> pt sp ┌───────────────┬───────────────┬────────────────┐