2 | import public Data.List1
3 | import public Data.Maybe
4 | import public Data.SnocList
5 | import public Data.String
7 | import Data.Buffer.Indexed
8 | import Data.ByteString
9 | import Sqlite3.Marshall
10 | import Sqlite3.Types
32 | record SQLTable where
46 | public export %inline
47 | table : String -> List Column -> SQLTable
58 | public export %inline
59 | AS : SQLTable -> String -> SQLTable
60 | AS (ST n _ cs) as = ST n as cs
63 | public export %inline
64 | ColTypes : SQLTable -> List SqliteType
65 | ColTypes = map type . cols
73 | FindCol : String -> List Column -> Maybe SqliteType
74 | FindCol s [] = Nothing
75 | FindCol s (x :: xs) = if x.name == s then Just x.type else FindCol s xs
82 | public export %inline
85 | -> (cs : List Column)
86 | -> {auto 0 p : IsJust (FindCol s cs)}
88 | ListColType s cs = fromJust (FindCol s cs)
94 | public export %inline
98 | -> {auto 0 p : IsJust (FindCol s t.cols)}
100 | TableColType s t = fromJust (FindCol s t.cols)
110 | data TColumn : (t : SQLTable) -> (tpe : SqliteType) -> Type where
114 | -> {auto 0 prf : IsJust (FindCol name t.cols)}
115 | -> TColumn t (TableColType name t)
118 | public export %inline
119 | (.name) : TColumn t x -> String
123 | public export %inline
127 | -> {auto 0 p : IsJust (FindCol name t.cols)}
128 | -> TColumn t (TableColType name t)
143 | Schema = SnocList SQLTable
155 | FindSchemaCol2 : (table, column : String) -> Schema -> Maybe SqliteType
156 | FindSchemaCol2 t c [<] = Nothing
157 | FindSchemaCol2 t c (sx :< x) =
158 | if x.as == t then FindCol c x.cols else FindSchemaCol2 t c sx
173 | FindSchemaCol1 : String -> Schema -> Maybe SqliteType
174 | FindSchemaCol1 n [< t] = FindCol n t.cols
175 | FindSchemaCol1 n (_:< ST "" "" cs) = FindCol n cs
176 | FindSchemaCol1 n _ = Nothing
185 | FindSchemaCol : String -> Schema -> Maybe SqliteType
186 | FindSchemaCol str s =
187 | case split ('.' ==) str of
188 | n:::[] => FindSchemaCol1 n s
189 | t:::[n] => FindSchemaCol2 t n s
198 | -> {auto 0 prf : IsJust (FindSchemaCol name s)}
200 | SchemaColType n s = fromJust (FindSchemaCol n s)
205 | SchemaHasCol : Schema -> String -> Bool
206 | SchemaHasCol [<] s = False
207 | SchemaHasCol (sx :< x) s = any ((s==) . name) x.cols || SchemaHasCol sx s
216 | record JColumn (s : Schema) (t : SQLTable) where
219 | {auto 0 p1 : SchemaHasCol s name === True}
220 | {auto 0 p2 : IsJust (FindCol name t.cols)}
223 | public export %inline
226 | -> {0 t : SQLTable}
228 | -> {auto 0 p1 : SchemaHasCol s name === True}
229 | -> {auto 0 p2 : IsJust (FindCol name t.cols)}
239 | record Table a where
241 | {auto torow : ToRow a}
242 | header : LAll (const String) (ToRowTypes a)
245 | hexChar : Bits8 -> Char
275 | encodeBytes : ByteString -> String
276 | encodeBytes = pack . (\x => 'X'::quote::x) . foldr acc [quote]
278 | %inline acc : Bits8 -> List Char -> List Char
279 | acc b cs = hexChar (b `shiftR` 4) :: hexChar (b .&. 0xf) :: cs
281 | encode : (t : SqliteType) -> Maybe (IdrisType t) -> String
282 | encode _ Nothing = "NULL"
283 | encode BLOB (Just v) = encodeBytes v
284 | encode TEXT (Just v) = v
285 | encode INTEGER (Just v) = show v
286 | encode REAL (Just v) = show v
288 | pad : SqliteType -> Nat -> String -> String
289 | pad BLOB k = padRight k ' '
290 | pad TEXT k = padRight k ' '
291 | pad INTEGER k = padLeft k ' '
292 | pad REAL k = padLeft k ' '
294 | center : Nat -> String -> String
296 | let ki := cast {to = Integer} (k `minus` length s)
299 | in replicate (cast pl) ' ' ++ s ++ replicate (cast pr) ' '
301 | maxLength : Nat -> String -> Nat
302 | maxLength n = max n . length
304 | barSep : LAll (const String) ts -> String
305 | barSep = fastConcat . intersperse " | " . forget
307 | bar : LAll (const Nat) ts -> String
308 | bar = fastConcat . intersperse "---" . map (`replicate` '-') . forget
313 | -> (header : LAll (const String) ts)
314 | -> (rows : List (LAll (Maybe . IdrisType) ts))
317 | let cells := map (hmapW encode) rs
318 | lengths := foldl (hzipWith maxLength) (hconst 0) (h :: cells)
319 | rows := map (barSep . hzipWithW pad lengths) cells
320 | header := barSep $
hzipWith center lengths h
321 | in fastUnlines (header :: bar lengths :: rows)
324 | prettyTable : Table a -> String
325 | prettyTable (T h rs) = prettyRows h (map toRow rs)
328 | printTable : HasIO io => Table a -> io ()
329 | printTable = putStrLn . prettyTable