做完rust全链路
This commit is contained in:
1 parent
e428265357
commit
2a4b446252
34 files changed
+1756
-1031
No files matched your search
@@ -8,29 +8,31 @@ import ChuSQL.Storage (MonadStorage (..))
|
||||
import ChuSQL.Syntax.AST (Expr (..))
|
||||
import Control.Monad (filterM)
|
||||
|
||||
-- 执行:按关系算子树真正算出结果行(Scan 阶段会给列名加上别名前缀)。
|
||||
-- 执行:按算子树算出结果行(Scan 阶段会加别名前缀)。
|
||||
|
||||
-- 投影:只保留清单里的列;哨兵 "*" 表示全部列。
|
||||
-- * 工具
|
||||
-- | 只保留清单里的列
|
||||
project :: [String] -> Row -> Row
|
||||
project ["*"] row = row
|
||||
project cs row = [(c, v) | (c, v) <- row, c `elem` cs]
|
||||
|
||||
-- 给一行里的每个列名加上别名前缀(如 "u.")。
|
||||
-- | 给列名加别名前缀
|
||||
addPrefix :: String -> Row -> Row
|
||||
addPrefix prefix = map (\(k, v) -> (prefix ++ k, v))
|
||||
|
||||
-- 索引查找的约定:主键列名是 "id"(优化器只在这种情况下才把过滤改写成 Lookup)。
|
||||
-- | 主键匹配条件(id = k)
|
||||
keyCondition :: Int -> Expr
|
||||
keyCondition k = Eq (Col "id") (LitInt k)
|
||||
|
||||
-- 扫描一张表;有别名就给每个列名加上前缀,JOIN 两边同名列靠它区分。
|
||||
-- | 扫描一张表
|
||||
evalScan :: Database -> Maybe String -> String -> Either String [Row]
|
||||
evalScan db mAlias tbl = do
|
||||
table <- lookupTable db tbl
|
||||
let prefix = maybe "" (++ ".") mAlias
|
||||
Right (map (addPrefix prefix) (tableRows table))
|
||||
|
||||
-- 执行关系代数运算:Scan / Lookup / Filter / Project / Sort / Limit / Join 各一支。
|
||||
-- * 求值
|
||||
-- | 纯求值(不需要存储)
|
||||
evalRelOp :: Database -> RelOp -> Either String [Row]
|
||||
evalRelOp db (Scan mAlias tbl) = evalScan db mAlias tbl
|
||||
evalRelOp db (Lookup tbl k) = do
|
||||
@@ -51,18 +53,18 @@ evalRelOp db (Limit n op) = do
|
||||
evalRelOp db (Join left right cond) = do
|
||||
lrows <- evalRelOp db left
|
||||
rrows <- evalRelOp db right
|
||||
let cross = [l ++ r | l <- lrows, r <- rrows] -- 笛卡尔积
|
||||
let cross = [l ++ r | l <- lrows, r <- rrows]
|
||||
filterM (evalCondForRow cond) cross
|
||||
|
||||
-- | Monadic 版本:Lookup 直接问存储要一行(走索引),其余算子照原样递归。
|
||||
-- | 单子求值:Lookup 问存储
|
||||
evalRelOpM :: (MonadStorage m) => Database -> RelOp -> m (Either String [Row])
|
||||
evalRelOpM db (Scan a t) = pure (evalScan db a t)
|
||||
evalRelOpM _ (Lookup t k) = do
|
||||
result <- lookupByKey t k
|
||||
pure $ case result of
|
||||
Left e -> Left e
|
||||
Right Nothing -> Right []
|
||||
Right (Just r) -> Right [r]
|
||||
evalRelOpM db (Scan a t) = pure (evalScan db a t)
|
||||
evalRelOpM db (Filter p x) = do
|
||||
result <- evalRelOpM db x
|
||||
pure $ do
|
||||
|
||||
Reference in new issue
Block a user