aboutsummaryrefslogtreecommitdiff
path: root/src/FSD/Db.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/FSD/Db.hs')
-rw-r--r--src/FSD/Db.hs211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/FSD/Db.hs b/src/FSD/Db.hs
new file mode 100644
index 0000000..38a822c
--- /dev/null
+++ b/src/FSD/Db.hs
@@ -0,0 +1,211 @@
+{-
+Copyright (C) 2022 Yuchen Pei.
+
+This file is part of fsd.
+
+fsd is free software: you can redistribute it and/or modify it under
+the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+fsd is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
+Public License for more details.
+
+You should have received a copy of the GNU Affero General Public
+License along with fsd. If not, see <https://www.gnu.org/licenses/>.
+
+-}
+
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeOperators #-}
+
+module FSD.Db where
+
+import Control.Monad
+import FSD.Copyright
+import Data.Text (Text)
+import Data.Text qualified as T
+import Database.SQLite.Simple
+import FSD.Types
+
+newtype FsDb = FsDb {getConn :: Connection}
+
+withFsDb :: FilePath -> (FsDb -> IO a) -> IO a
+withFsDb path f = withConnection path (f . FsDb)
+
+-- creations
+
+initConn :: FsDb -> IO ()
+initConn (FsDb conn) = do
+ execute_
+ conn
+ "CREATE TABLE IF NOT EXISTS sources \
+ \( package TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE \
+ \, version TEXT NOT NULL \
+ \, file TEXT NOT NULL \
+ \, homepage TEXT \
+ \)"
+ execute_
+ conn
+ "CREATE TABLE IF NOT EXISTS packages \
+ \( package TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE \
+ \, version TEXT NOT NULL \
+ \, homepage TEXT \
+ \, tags TEXT NOT NULL \
+ \)"
+ execute_
+ conn
+ "CREATE TABLE IF NOT EXISTS translation \
+ \( package TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE \
+ \, shortDesc TEXT NOT NULL \
+ \, fullDesc TEXT NOT NULL \
+ \)"
+ execute_
+ conn
+ "CREATE TABLE IF NOT EXISTS changelog \
+ \( package TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE \
+ \, version TEXT NOT NULL \
+ \, author TEXT NOT NULL \
+ \, date TEXT NOT NULL \
+ \)"
+ execute_
+ conn
+ "CREATE TABLE IF NOT EXISTS copyright \
+ \( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT \
+ \, package TEXT NOT NULL \
+ \, entryId INTEGER NOT NULL \
+ \, copyright TEXT \
+ \, license TEXT NOT NULL \
+ \, note TEXT \
+ \, CONSTRAINT uniqname UNIQUE (package, entryId) ON CONFLICT REPLACE \
+ \)"
+ execute_
+ conn
+ "CREATE TABLE IF NOT EXISTS upstream \
+ \( package TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE \
+ \, name TEXT \
+ \, contacts TEXT \
+ \, sources TEXT \
+ \)"
+
+-- insertions
+
+insertSource :: FsDb -> Source -> IO ()
+insertSource (FsDb conn) source =
+ execute conn "INSERT INTO sources VALUES (?,?,?,?)" source
+
+insertPackage :: FsDb -> Package -> IO ()
+insertPackage (FsDb conn) package =
+ execute conn "INSERT INTO packages VALUES (?,?,?,?)" package
+
+insertTranslation :: FsDb -> Translation -> IO ()
+insertTranslation (FsDb conn) translation =
+ execute conn "INSERT INTO translation VALUES (?,?,?)" translation
+
+insertFSDChangeLogEntry :: FsDb -> FSDChangeLogEntry -> IO ()
+insertFSDChangeLogEntry (FsDb conn) change =
+ execute conn "INSERT INTO changelog VALUES (?,?,?,?)" change
+
+insertCopyright :: FsDb -> Copyright -> IO ()
+insertCopyright db (Copyright package licenses) =
+ zipWithM_ (insertLicense db package) [0 ..] licenses
+
+insertUpstream :: FsDb -> Upstream -> IO ()
+insertUpstream (FsDb conn) upstream =
+ execute conn "INSERT INTO upstream VALUES (?,?,?,?)" upstream
+
+insertLicense :: FsDb -> Text -> Int -> LicenseInfo -> IO ()
+insertLicense (FsDb conn) package idx (LicenseInfo copyright license note) =
+ execute
+ conn
+ "INSERT INTO copyright (package,entryId,copyright,license,note) \
+ \VALUES (?,?,?,?,?)"
+ (package, idx, copyright, license, note)
+
+-- queries
+getDbAll :: FsDb -> IO [Source :. Package :. Translation :. FSDChangeLogEntry :. Upstream]
+getDbAll (FsDb conn) =
+ query_
+ conn
+ "SELECT sources.*,packages.*,translation.*,changelog.*,upstream.* \
+ \FROM sources JOIN packages USING (package,version)\
+ \ JOIN changelog USING (package,version)\
+ \ JOIN translation USING (package)\
+ \ JOIN upstream USING (package)\
+ \"
+
+getDbPkgNames :: FsDb -> IO [Text]
+getDbPkgNames (FsDb conn) = do
+ rows <- query_ conn
+ "SELECT DISTINCT package\
+ \ FROM sources JOIN packages USING (package,version)\
+ \ JOIN changelog USING (package,version)\
+ \ JOIN translation USING (package)\
+ \ JOIN upstream USING (package)\
+ \ JOIN copyright USING (package)\
+ \"
+ return $ fromOnly <$> rows
+
+getDbAllTypes :: Text -> FsDb -> IO (Maybe (Source :. Package :. Translation :. FSDChangeLogEntry :. Upstream))
+getDbAllTypes pkgName (FsDb conn) = do
+ results <- query
+ conn
+ "SELECT sources.*,packages.*,translation.*,changelog.*,upstream.* \
+ \FROM sources JOIN packages USING (package,version)\
+ \ JOIN changelog USING (package,version)\
+ \ JOIN translation USING (package)\
+ \ JOIN upstream USING (package) \
+ \WHERE package = ?\
+ \" (Only pkgName)
+ return $ case results of
+ [source] -> Just source
+ otherwise -> Nothing
+
+getDbSource :: Text -> FsDb -> IO (Maybe Source)
+getDbSource pkgName (FsDb conn) = do
+ results <- query conn "SELECT * FROM sources WHERE package = ?" (Only pkgName)
+ return $ case results of
+ [source] -> Just source
+ otherwise -> Nothing
+
+getDbPackage :: Text -> FsDb -> IO (Maybe Package)
+getDbPackage pkgName (FsDb conn) = do
+ results <- query conn "SELECT * FROM packages WHERE package = ?" (Only pkgName)
+ return $ case results of
+ [package] -> Just package
+ otherwise -> Nothing
+
+getDbTranslation :: Text -> FsDb -> IO (Maybe Translation)
+getDbTranslation pkgName (FsDb conn) = do
+ results <- query conn "SELECT * FROM translation WHERE package = ?" (Only pkgName)
+ return $ case results of
+ [translation] -> Just translation
+ otherwise -> Nothing
+
+getDbFSDChangeLogEntry :: Text -> FsDb -> IO (Maybe FSDChangeLogEntry)
+getDbFSDChangeLogEntry pkgName (FsDb conn) = do
+ results <- query conn "SELECT * FROM changelog WHERE package = ?" (Only pkgName)
+ return $ case results of
+ [entry] -> Just entry
+ otherwise -> Nothing
+
+getDbUpstream :: Text -> FsDb -> IO (Maybe Upstream)
+getDbUpstream pkgName (FsDb conn) = do
+ results <- query conn "SELECT * FROM upstream WHERE package = ?" (Only pkgName)
+ return $ case results of
+ [upstream] -> Just upstream
+ otherwise -> Nothing
+
+getDbCopyright :: Text -> FsDb -> IO (Maybe Copyright)
+getDbCopyright pkgName (FsDb conn) = do
+ results <-
+ query
+ conn
+ "SELECT copyright,license,note FROM copyright WHERE package = ?"
+ (Only pkgName) ::
+ IO [LicenseInfo]
+ return $
+ if (null results) then Nothing else Just $ Copyright pkgName results