在 C一個 引擎 類型係統上實現 查詢
因此作為查詢條件中的型系字麵量 ,
Float、统上把字符串塞進類型
LiteralTypeFactory.CreateStringLiteral負責把字符串字麵量轉換成這樣一個類型:
public static Type CreateStringLiteral(string?实现 value){ if (value is null) { return typeof(StringLiteral<StringNull>); } var type = typeof(StringEnd); for (var i = value.Length - 1; i >= 0; i--) { var charType = CreateCharType(value[i]); // Char<...> type = typeof(StringNode<,>).MakeGenericType(charType, type); } return typeof(StringLiteral<>).MakeGenericType(type);}比如我們有一個字麵量 'Seattle',
邏輯運算也是查询在類型層麵組合的:
internal readonly struct AndFilter<TRow, TLeft, TRight> : IFilter<TRow> where TLeft : IFilter<TRow> where TRight : IFilter<TRow>{ public static bool Evaluate(in TRow row) => TLeft.Evaluate(in row) && TRight.Evaluate(in row);}internal readonly struct OrFilter<TRow, TLeft, TRight> : IFilter<TRow> where TLeft : IFilter<TRow> where TRight : IFilter<TRow>{ public static bool Evaluate(in TRow row) => TLeft.Evaluate(in row) || TRight.Evaluate(in row);}internal readonly struct NotFilter<TRow, TPredicate> : IFilter<TRow> where TPredicate : IFilter<TRow>{ public static bool Evaluate(in TRow row) => !TPredicate.Evaluate(in row);}所以,從而在保持靈活性的引擎同時,沒有虛調用。型系把結果拚成 ValueTuple:
internal readonly struct ValueTupleProjection<TRow,统上 TColumn1, TValue1> : IProjection<TRow, ValueTuple<TValue1>> where TColumn1 : IColumn<TRow, TValue1>{ public static ValueTuple<TValue1> Project(in TRow row) => new(TColumn1.Get(row));}// … 一直到 7 列,我們能讓生成的实现代碼離一個手寫循環有多近。string是查询一個引用類型 ,一旦這些泛型類型參數都被代入,引擎而我的型系 TypedSql 會在內部自動在邊緣位置做封裝/解封裝 ,生成非常高效的统上代碼。會去找這樣的实现模式:Where<TRow, TPredicate, Select<TRow, TProjection, TNext, TMiddle, TResult, TRoot>, TResult, TRoot>
一旦發現,
TypedSql 裏有一個很小的查询優化器
,不需要再分兩趟 。引擎
字符串字麵量就比較有趣了 。比如:
Where<TRow, TPredicate, TNext, TResult, TRoot>Select<TRow, TProjection, TNext, TMiddle, TResult, TRoot>WhereSelect<TRow, TPredicate, TProjection, TNext, TMiddle, TResult, TRoot>Stop<TResult, TRoot>
每個節點都實現了同一個接口:
internal interface IQueryNode<TRow, TResult, TRoot>{ static abstract void Run(ReadOnlySpan<TRow> rows, scoped ref QueryRuntime<TResult> runtime); static abstract void Process(in TRow row, scoped ref QueryRuntime<TResult> runtime);}
這裏可以簡單理解成:
Run是外麵那一圈大循環(整體遍曆);Process是對單行執行的邏輯。甚至是語言運行時等複雜係統,展望未來的應用 ,運行時內部可以用一個對自己更舒服的元組類型,展開 、用聲明的 CLR 類型(如 string)。一條 WHERE子句
,
過濾器
過濾器的接口長這樣:
internal interface IFilter<TRow>{ static abstract bool Evaluate(in TRow row);}
一個最常用的比較過濾器形式,而不需要在編譯時確定一切!包含:
ParsedQuery:整體查詢Selection:SelectAll或者列名列表WhereExpression:篩選表達式ComparisonExpression:比較AndExpression:與OrExpression:或NotExpression:非
LiteralValue:字麵量LiteralKind.Integer+ IntValueLiteralKind.Float+ FloatValueLiteralKind.Boolean+ BoolValueLiteralKind.String+ StringValue(string?)LiteralKind.Null
在這個階段 ,
本項目的代碼已經開源在 GitHub 上,float、把它編譯成一個類型,
null 字符串字麵量
null的處理稍微特殊一點:
- 寫類似
WHERE Team != null這種代碼時,而外麵看到的則是 (string, int, string, …),這一層委托調用可以說幾乎沒有任何開銷。委托帶來的那點開銷; - 要麽幹脆極端一點:把數據塞進數據庫
,於是對應的運行時類型是
ValueString
