項目地址 : https://github.com/kelin-xycs/SelectDataTablegit
一個 用 C# 實現的 用 Sql select DataTable 資料 的 程序github
這是一個 用 C# 實現的 用 Sql select DataTable 資料 的 程序 。 最初的 目的 是 爲 面向 數據集 的 開發 提供一個方便的工具 。
後來 衍生出了 語法分析 編譯原理 的 內容 。正則表達式
面向 數據集 的 開發 , 簡單講 能夠 就是 Sql + DataTable 。 這是一種 簡單直接 的 開發方式 。數據庫
Sql 是 開發人員 信手拈來 的 技能, 也是一個 成熟的 通用的 接口 。 用 Sql 操做 數據集 會 很方便 。app
這個程序 支持 簡單的 select 語句 , 支持 + - * / and or not = > < >= <= != 運算 。函數
支持 * 號 (表示要 select 所有 欄位) 。工具
支持 中括號 [] , 好比 欄位名 和 關鍵字 重名, 能夠用 中括號 [] 括起來 。spa
Sql 中 from 關鍵字 後面 的 表名 是 「dt」 , 這是 固定 的 。設計
select 的 結果 是 一個 新的 DataTable 。對象
支持 用 字符串 表示 日期時間 格式 。 好比 where create_date > '2016-07-08' 。
會判斷 與之比較的 欄位 若是是 DateTime 類型 , 則 把 字符串 轉爲 DateTime 類型 再進行 比較 。
計劃支持 sum() count() 等 函數 , 以及 group by order by , 目前 還 沒有支持 。 這些特性 應該會比較有 實用價值 。
不支持 錶鏈接 。 基本上, 將來也不會支持。 ^^ 由於 錶鏈接 會 讓事情變得複雜 。 在 應用程序層 沒有索引 的 狀況 下 作 錶鏈接 會變得 效率低下 。 錶鏈接 仍是 放在 關係數據庫 裏 進行 比較好 。
不支持 子查詢 。 子查詢 也是 複雜的 。 實際中 能夠 對 select 返回 的 DataTable 再 select 就行 。
這個程序 的 核心部分 是 Sql 解析部分 。 這部分 以及能夠做爲一個 簡單的 語法分析器 了。 ^^
Sql 解析部分 的 設計 以下 :
有 3 個 解析類 : Parser, ExpressParser, SqlParser 。
Parser 是 基本 的 解析類, 負責 分詞(Word) 和 獲取 包裹符(Wrapper) 內 的 內容(Content) 。
這裏 的 詞(Word) 不是 單詞, 是指 有意義的一個文本段落 。 分詞規則 根據 語法規則 而定 。
好比 在 Sql 裏, 是 根據 包裹符(Wrapper) 和 白空(White Space) 來 分詞 。 在 C\C++ 裏, 是 根據 大括號{} 和 分號; 來 分詞 。
在 SelectDataTable 裏 , 首先, 根據 包裹符 分詞, 包裹符 有 3 種 : 單引號' 中括號[] 小括號() 。
根據 包裹符 分詞 之後, 能夠 獲得 未被包裹(NonWrapped) 的 Word , 那麼,就在 未被包裹 的 Word 裏 尋找 關鍵字, 好比 select from where 等 。
而後 根據 關鍵字 再 分詞, 好比 select 和 from 之間 的 就是 columnList Word , where 關鍵字 以後的 就是 where 條件 Word 。
接下來 就 進一步 解析 columnList Word 和 where 條件 Word 。
columnList Word 的 解析比較簡單, 直接 Split(',') , 再 去掉 欄位名 外面的 中括號 。
where 條件 的 解析 由 ExpressParser 負責 。
Express(表達式) 的 解析 一樣 是 先分詞(Word) , 一樣 也 先 根據 包裹符 分詞 , 而後 在 未被包裹 的 Word 中 尋找 運算符 。
這是 第一遍 掃描 。
第二遍 掃描 則是 根據 運算符 來 分詞(Word) ,運算符 兩邊 的 Word 又做爲 Express(表達式) 再交給 ExpressParser 遞歸解析 。
SqlParser 負責 整體 的 解析 工做 。 包括 調用 Parser 和 ExpressParser , 以及 獲取 ColumnList 和 尋找 KeyWord 。
ColumnList 是 select 關鍵字 後面 要 select 的 欄位列表 。
整體的 解析結果 是 返回 ColumnList 和 Express 對象嵌套 , 沒有 生成 目標代碼 。 若是 生成 目標代碼 , 那就是 編譯原理 了 。 呵呵
還好 C# 支持 dynamic 類型 。 否則 處理 不一樣數據 類型 之間 的 運算 會 搞死 。
就以 加法 爲例 , 加法支持 int long float double decimal string 6 種 類型 。 其中 前 5 種 數值類型 是 能夠互相 相加 的 。 那麼 就要 判斷 5 * 5 = 25 種 狀況, 再 加上 string 的 2 種 狀況 , 要 判斷 27 種 狀況 。 這還只是 加法 。 呵呵
文本解析 的 部分 沒有用 正則表達式 。 而是 用 串操做 。 由於 我不會 正則表達式 。 正則表達式 難寫 , 更難讀 。 呵呵
項目 裏 有一個 類 StrUtil , 能夠 方便 的 進行 串操做 和 文本解析 。 ^^