module Language.SQL.Keyword.Internal.Type (
Keyword (..), word, wordShow,
fromDString, toDString,
DString, dString, showDString, isEmptyDString
) where
import Data.String (IsString(..))
import Data.List (find)
import Data.Monoid (Monoid (..), (<>))
newtype DString = DString (String -> String)
dString :: String -> DString
dString = DString . (++)
showDString :: DString -> String
showDString (DString f) = f []
isEmptyDString :: DString -> Bool
isEmptyDString = null . showDString
instance Eq DString where
x == y = showDString x == showDString y
instance Show DString where
show = showDString
instance Read DString where
readsPrec _ s = [(dString s, [])]
instance Monoid DString where
mempty = DString id
DString f `mappend` DString g = DString $ f . g
dspace :: DString
dspace = dString " "
data Keyword = SELECT | ALL | DISTINCT | ON
| GROUP | COUNT | SUM | AVG | MAX | MIN | EVERY | ANY | SOME
| CUBE | ROLLUP | GROUPING | SETS | HAVING
| FOR
| ORDER | BY | ASC | DESC | NULLS | LAST
| OFFSET
| LIMIT
| FETCH | FIRST | NEXT | PERCENT
| ROW | ROWS | ONLY | TIES
| UNION | EXCEPT | INTERSECT
| DELETE | USING | RETURNING
| FROM | AS | WITH
| JOIN | INNER | LEFT | RIGHT | FULL | NATURAL | OUTER
| UPDATE | SET | DEFAULT
| WHERE
| INSERT | INTO | VALUES
| MERGE
| OVER | PARTITION
| DENSE_RANK | RANK | ROW_NUMBER
| PERCENT_RANK | CUME_DIST
| LAG | LEAD | FIRST_VALUE | LAST_VALUE
| CASE | END | WHEN | ELSE | THEN
| LIKE | SIMILAR
| AND | OR | NOT
| EXISTS
| IS | NULL | IN
| DATE | TIME | TIMESTAMP | TIMESTAMPTZ | INTERVAL
| Sequence !DString
deriving (Read, Show)
fromDString :: DString -> Keyword
fromDString = Sequence
toDString :: Keyword -> DString
toDString = d where
d (Sequence ds) = ds
d w = dString $ show w
word :: String -> Keyword
word = fromDString . dString
instance IsString Keyword where
fromString s' = found (find ((== "") . snd) (reads s')) s' where
found Nothing s = word s
found (Just (w, _)) _ = w
instance Monoid Keyword where
mempty = fromDString mempty
a `mappend` b = fromDString $ toDString a `append'` toDString b where
append' p q
| isEmptyDString p = q
| isEmptyDString q = p
| otherwise = p <> dspace <> q
wordShow :: Keyword -> String
wordShow = d where
d (Sequence s) = showDString s
d w = show w
instance Eq Keyword where
x == y = wordShow x == wordShow y