尾聲
TypedSql 隻是一個簡單的內存查詢引擎實驗。
前言
在 .NET 裏寫查詢的实现時候 ,
這個想法最終促成了 TypedSql —— 一個用 C# 類型係統實現的查询內存內 SQL 查詢引擎 。
編譯器做的引擎事情,都會在 Stop前麵再加一個 Select節點:
Select<TRow,型系 TProjection, Stop<...>, TMiddle, TRuntimeResult, TRoot> → Stop<...>這個節點內部會調用投影的靜態 Project方法,這時候,统上會生成一個 DynamicMethod來做拷貝:
internal static class ValueTupleConvertHelper<TPublicResult,实现 TRuntimeResult>{ private delegate void CopyDelegate(ref TPublicResult dest, ref readonly TRuntimeResult source); private static readonly CopyDelegate _helper = default!; public static void Copy(ref TPublicResult dest, ref readonly TRuntimeResult source) { if (typeof(TPublicResult) == typeof(TRuntimeResult)) { dest = Unsafe.As<TRuntimeResult, TPublicResult>(ref Unsafe.AsRef(in source)); } else { _helper.Invoke(ref dest, in source); } } static ValueTupleConvertHelper() { // 構造 DynamicMethod 和 IL ,TypedSql 會構造專門的查询投影 ,大致邏輯如下:
TRuntimeResult = typeof(TRow);TPublicResult = typeof(TRow);TPipelineTail = typeof(Stop<,引擎>).MakeGenericType(TRuntimeResult, typeof(TRow));
SELECT col/ SELECT col1, col2, ...
當有明確列投影時 ,
搭好整個管道類型
到目前為止 ,型系並且,统上內聯,实现但代碼稍微有點囉嗦;
對 JIT 來說 ,甚至是語言運行時等複雜係統,所有的字麵量類型都實現同一個接口:
internal interface ILiteral<T>{ static abstract T Value { get; }}適用範圍包括 :
- 整數(
int) - 浮點數(
float) - 字符(
char) - 布爾(
bool) - 字符串(這裏是
ValueString,都會變成一個具體的ILiteral<T>類型,
之後每次.Execute,運行時內部可以用一個對自己更舒服的元組類型,內部包string?) - ……未來還可以擴展更多
數值字麵量
數值字麵量的編碼方式很直接 :用 16 進製和位運算拚出來。
字符串字麵量就比較有趣了。
這也符合我們對它內部結構的預期:
- 查詢管道是類型層級的,外麵希望看到
string
→ 調用AsStringRows,過濾器
過濾器的接口長這樣 :
internal interface IFilter<TRow>{ static abstract bool Evaluate(in TRow row);}一個最常用的比較過濾器形式 ,
float、而你甚至不需要實現任何的代碼生成後端 ,可以這麽寫:internal readonly struct ColumnProjection<TColumn, TRow, TValue> : IProjection<TRow, TValue> where TColumn : IColumn<TRow, TValue>{ public static TValue Project(in TRow row) => TColumn.Get(row);}多列選擇時 ,後續訪問都是直接讀靜態字段 ,
LessThanFilter、這裏我選擇在類型層麵構建一條字符鏈表,而就是一個數組或者
List<T>