module StateSizedIO.LIB.DB.Query where
open import Data.Product renaming (proj₁ to fst; proj₂ to snd)
open import Data.Bool
open import Data.String renaming (_++_ to _+++_) hiding (show)
open import Data.List hiding (lookup)
open import Data.Vec hiding (lookup; _++_)
open import Function
open import Data.Integer renaming (show to showℤ)
import StateSizedIO.LIB.DB.Dictionary
open import StateSizedIO.LIB.DB.Schema
open StateSizedIO.LIB.DB.Dictionary {String} _==_
open import StateSizedIO.LIB.DB.DBUniverse
data ExprType : Set where
bool : ExprType
ftype : FieldType -> ExprType
data Expr (t : TableType) : ExprType -> Set where
_===_ : forall {a} -> Expr t a -> Expr t a -> Expr t bool
!_ : forall x {p : HasKey x t} -> Expr t (ftype (fst (lookup x t {p})))
val : forall {a} -> Field a -> Expr t (ftype a)
data Query (s : Schema) : TableType -> Set where
read : (x : TableName){p : HasKey x s} -> Query s (lookup x s {p})
_⊗_ : forall {t t'}{p : Disjoint t t'} ->
Query s t -> Query s t' -> Query s (t ++ t')
proj : forall {t} xs {p : HasKeys xs t} ->
Query s t -> Query s (project xs t {p})
select : forall {t} -> Expr t bool -> Query s t -> Query s t
data SQL : Set where
SELECT_FROM_WHERE_ : List FieldName -> List TableName -> List String -> SQL
sepBy : String -> List String -> String
sepBy _ [] = ""
sepBy _ (x ∷ []) = x
sepBy i (x ∷ xs) = x +++ i +++ sepBy i xs
showField : forall {a} -> Field a -> String
showField {string} s = "'" +++ s +++ "'"
showField {integer} n = showℤ n
showExpr : forall {t a} -> Expr t a -> String
showExpr (e₁ === e₂) = showExpr e₁ +++ " = " +++ showExpr e₂
showExpr (! x) = x
showExpr (val c) = showField c
showSQL : SQL -> String
showSQL (SELECT as FROM ts WHERE []) =
"SELECT " +++ sepBy ", " as +++ " FROM " +++ sepBy ", " ts
showSQL (SELECT as FROM ts WHERE cs) =
"SELECT " +++ sepBy ", " as +++ " FROM " +++ sepBy ", " ts +++
" WHERE " +++ sepBy " AND " cs
toSQL : forall {s t} -> Query s t -> SQL
toSQL {s} (read x {p}) = SELECT (Data.List.map fst (lookup x s {p})) FROM x ∷ [] WHERE []
toSQL (q₁ ⊗ q₂) with toSQL q₁ | toSQL q₂
... | SELECT as₁ FROM ts₁ WHERE cs₁
| SELECT as₂ FROM ts₂ WHERE cs₂ = SELECT (as₁ ++ as₂) FROM (nub (ts₁ ++ ts₂)) WHERE (cs₁ ++ cs₂)
toSQL (proj as q) with toSQL q
... | SELECT _ FROM ts WHERE cs = SELECT as FROM ts WHERE cs
toSQL (select c q) with toSQL q
... | SELECT as FROM ts WHERE cs = SELECT as FROM ts WHERE (showExpr c ∷ cs)