事务模型
This commit is contained in:
1 parent
274b7fcdcc
commit
045ccc2dc0
20 files changed
+1519
-294
No files matched your search
@@ -15,6 +15,9 @@ module ChuSQL.Core.Model
|
||||
, colNames
|
||||
, colType
|
||||
, lookupTable
|
||||
, resolveTable
|
||||
, lastTablePart
|
||||
, deriveQualifier
|
||||
, allColumns
|
||||
, qualify
|
||||
, unqualify
|
||||
@@ -470,6 +473,32 @@ colType t c = lookup c (tableCols t)
|
||||
lookupTable :: Database -> String -> Either String Table
|
||||
lookupTable db t = maybe (Left ("unknown table: " ++ t)) Right (lookup t db)
|
||||
|
||||
-- | 取表名引用的最后一段
|
||||
lastTablePart :: String -> String
|
||||
lastTablePart = reverse . takeWhile (/= '.') . reverse
|
||||
|
||||
-- | 推导列前缀:有别名用别名,否则取表名末段
|
||||
deriveQualifier :: Maybe String -> String -> String
|
||||
deriveQualifier (Just a) _ = a
|
||||
deriveQualifier Nothing t = lastTablePart t
|
||||
|
||||
-- | 按名查表并返回 schema 键:精确、前缀、唯一后缀
|
||||
resolveTable :: Database -> String -> Either String (String, Table)
|
||||
resolveTable db name = case lookup name db of
|
||||
Just table -> Right (name, table)
|
||||
Nothing
|
||||
| '.' `elem` name, Just table <- lookup bare db -> Right (bare, table)
|
||||
| [(key, table)] <- suffixed -> Right (key, table)
|
||||
| otherwise -> Left (miss suffixed)
|
||||
where
|
||||
-- | 引用里去掉库前缀的那一段
|
||||
bare = lastTablePart name
|
||||
-- | schema 里以这个表名收尾的键:`sales.users` 能推出裸表名引用
|
||||
suffixed = [(key, table) | (key, table) <- db, ('.' : name) `isSuffixOf` key]
|
||||
-- | 一个候选都没有就是查无此表,多于一个就是有歧义
|
||||
miss [] = "unknown table: " ++ name
|
||||
miss _ = "ambiguous table: " ++ name
|
||||
|
||||
-- | 通配列名
|
||||
allColumns :: String
|
||||
allColumns = "*"
|
||||
@@ -491,5 +520,5 @@ resolveColumn name env = case [(k, v) | (k, v) <- env, matches k] of
|
||||
[] -> Left ("unknown column: " ++ name)
|
||||
_ -> Left ("ambiguous column: " ++ name)
|
||||
where
|
||||
-- | 裸名或带后缀的名称
|
||||
matches k = k == name || ('.' : name) `isSuffixOf` k
|
||||
-- | 裸名、补充了库前缀的写法,或 schema 键自带库前缀的写法
|
||||
matches k = k == name || ('.' : name) `isSuffixOf` k || ('.' : k) `isSuffixOf` name
|
||||
@@ -3,6 +3,7 @@
|
||||
module ChuSQL.Core.Protocol (
|
||||
SchemaColumn (..),
|
||||
Request (..),
|
||||
TxnOp (..),
|
||||
Response (..),
|
||||
TableInfo (..),
|
||||
Account (..),
|
||||
@@ -96,6 +97,35 @@ data Request
|
||||
| ReqDropColumn String String
|
||||
| ReqReplaceSchema String [SchemaColumn] [Row]
|
||||
| ReqListCatalog
|
||||
| ReqApplyTransaction [TxnOp]
|
||||
|
||||
-- | 事务提交里的一条写操作
|
||||
data TxnOp
|
||||
= TxnUpsert String [Row]
|
||||
| TxnDelete String [Int]
|
||||
| TxnReplace String [Row]
|
||||
deriving (Show, Eq)
|
||||
|
||||
-- | 事务操作编码成 JSON
|
||||
instance ToJSON TxnOp where
|
||||
toJSON (TxnUpsert t rs) =
|
||||
object
|
||||
[ "op" .= ("upsert" :: T.Text)
|
||||
, "table" .= t
|
||||
, "rows" .= map rowToJSON rs
|
||||
]
|
||||
toJSON (TxnDelete t ks) =
|
||||
object
|
||||
[ "op" .= ("delete" :: T.Text)
|
||||
, "table" .= t
|
||||
, "ids" .= ks
|
||||
]
|
||||
toJSON (TxnReplace t rs) =
|
||||
object
|
||||
[ "op" .= ("replace" :: T.Text)
|
||||
, "table" .= t
|
||||
, "rows" .= map rowToJSON rs
|
||||
]
|
||||
|
||||
-- | 请求编码成 JSON
|
||||
instance ToJSON Request where
|
||||
@@ -201,6 +231,11 @@ instance ToJSON Request where
|
||||
, "rows" .= map rowToJSON rs
|
||||
]
|
||||
toJSON ReqListCatalog = object ["method" .= ("list_catalog" :: T.Text)]
|
||||
toJSON (ReqApplyTransaction ops) =
|
||||
object
|
||||
[ "method" .= ("apply_transaction" :: T.Text)
|
||||
, "ops" .= ops
|
||||
]
|
||||
|
||||
-- | 一张表的梗概:列、行数、索引与列统计
|
||||
data TableInfo = TableInfo
|
||||
|
||||
Reference in new issue
Block a user