SQL Search
本頁定義跨來源搜尋的 provider、排序/合併、索引與清單的批次複製;完整度、進度與停止見 完整度與進度,命中標示與啟用結果分別見命中高亮及結果導航。
入口是 SqlAssist 工具列的 Search(位於 History/Favorites 後)與 工具 → SqlAssist → SQL Search;完整名稱留在 Tooltip 與選單,沒有鍵盤捷徑。
provider 契約
來源實作 Core/Search/ISearchProvider,宣告分類並把命中推進 ISearchSink; SearchAggregator 負責聚合。串流 sink 讓快速的名稱命中先顯示,不必等最慢來源完成。
加一個新來源
- 實作
ISearchProvider;跨版本不得更名Id。 - 提供分類表;分類
Id會寫入偏好,同樣不得更名。 - 提供自己的導航酬載,掛在
SearchHit.ActivatePayload;Core 不解讀。伺服器上的東西實作ISqlSearchTarget,帶著 provider 建構時收到的SqlSearchOrigin,見結果導航。 - 在
Ssms22/Search/SqlSearchProviders加入來源類別。 - 在
SqlSearchActivation加入對應分支。辨識酬載型別只准發生在那裡,清單樣板、圖示與 預覽只讀SearchHit的欄位;預覽要不要讀定義也問它(DefinitionOf)。
provider 必須在取資料前套用 SearchQuery.Targets 與分類;每個要搜的東西先宣告成目標並說出結局, 見完整度與進度;TryReport 回 false 立即停止;DbException 降級為那個目標 讀不到,不外擲。種類下拉、清單與預覽不因新來源改動。
兩條篩選軸
SearchCategory 是物件種類,SearchMatchTarget 是命中位置。資料行命中仍歸屬資料表, 否則「只看資料表」會錯誤排除資料行命中的表。種類由各 provider 宣告;Core 不依賴 Metadata 的 SqlObjectKind,目錄來源對應在 SqlCatalogSearchCategories。目錄物件一種一個分類, 同義字、序列與資料表型別不併成收納桶:種類在下拉裡不佔工具列,併著的話只要同義字的人篩不出來。
排名、合併與名稱/本文
名稱與資料行在未開修飾時用 FuzzyMatcher;大小寫或全字任一開啟後改走 SearchIdentifierMatch 的字面比對。定義本文一律用字面子字串,分數是出現次數; 模糊搜尋本文會讓長定義以零散字母取得不合理高分。字面命中仍向 FuzzyMatcher 取分, 避免同一批結果出現第二套排序。名稱、本文與高亮換算共用 SearchQuery.Matcher,見唯一實作。
SearchMatchTargets.GroupOrder 先依名稱、資料行、本文分組,再於組內比分數;不同尺度不互比。 同一物件只有一列,去重鍵不含命中位置或資料行名稱。代表取排名最高者,其餘攤平放入 SearchHit.Merged;呈現讀 SearchHit.Matches,才能保留所有命中原因。
資料行命中的標題與去重鍵都必須指向所屬物件,不接資料行名稱。
失敗與讀不到
Failures 是 provider 擲了例外,讀不到是目標的結局;兩者不互相冒充。失敗訊息使用 ISearchProvider.DisplayName,診斷才用穩定但不面向使用者的 Id。
SearchUnavailableKind 只分 Unknown 與 Denied,只有 provider 收到明確權限錯誤才給 Denied。
SqlServerErrorCodes 將 229、230、262、297、300、916、4060 視為權限錯誤;18456 是認證失敗。 錯誤碼以反射讀取,因 Metadata 只依賴 System.Data、netstandard2.0 的 DbException 沒有 Number, 執行期例外則來自 Microsoft.Data.SqlClient。
索引策略
SqlCatalogSearchIndex 不與按需載入的 SqlMetadataCatalog 共用資料,但必須共用連線與快取鍵。 搜尋一次需要整批資料,若灌入補全的常駐快取,兩邊的載入與淘汰策略會互相干擾。
索引分兩段:物件、資料行、結構描述先載入;只有搜尋本文才以 TryAddDefinitions 補定義, 不重掃第一段。版本戳同時使用 MAX(modify_date) 與物件數,才能辨識刪除最後修改物件。 重新整理呼叫 Invalidate,保留可增量更新的資料;換連線才 Clear。
建索引是快取自己的工作(SqlCatalogSearchIndexBuild),不跟著輪次取消:每打一個字就丟掉建到一半的 索引,大資料庫永遠建不完。同一個資料庫同時只建一份,後到的輪次接著等;只有 Clear 與 CancelBuilds (停止、收起視窗)會停下建置。同時建幾份有上限,伺服器端比對本文共用同一組名額。
定義本文是快取,比對的完整度不跟著它打折。單一資料庫超過 64 MiB 時整份不留,改由伺服器端比對 (TextOnServer、SqlCatalogServerTextSearch);整體快取 512 MiB,滿了先把最久沒用到那幾份的本文讓給伺服器端, 還不夠才整份淘汰,但至少保留一份。改到伺服器端的資料庫留在那一種直到換連線,否則放不下的資料庫每一輪都 互相擠掉重建。伺服器端以不分大小寫的 LIKE 粗篩,比對規則由 SearchQuery.Matcher 再比一次。
只索引這一輪真的要搜的資料庫(勾選的那幾個,或範圍是「全部」時的每一個);禁止在還沒有人搜之前先索引。
多選與批次複製
多選互動與 SQL Memory 同一份,見清單列。一輪的答案整份在手上(分批套上只為了 分攤版面),所以沒有背景讀取:全選時還沒套上的那幾批先補完再複製。勾選以 DedupeKey 為鍵, 重新整理與重排照鍵保留。
欄位是名稱(限定名稱,沒有路徑概念的來源用標題)、種類、伺服器、資料庫、命中部位與命中資料行 (SqlSearchRow.CopyColumns);伺服器與資料庫取 provider 的脈絡膠囊,沒有就留空,不含定義本文。 平常的 Ctrl+C 仍是複製焦點列的限定名稱。
回饋與列操作
沒有狀態列。筆數、完整度與「這一輪失敗、清單是上一輪的」寫在清單頁尾 (SqlSearchBrowserModel.Footer,呈現與 SQL Memory 共用);按下去的結果與失敗走通知,種類是 Search,移至定義與在物件總管中選取歸 Navigation、由 SqlSearchActivation 自己送。同一句失敗 只送一次,否則讀不到的來源會在每打一個字時跳一次。
列操作只有一份(SqlSearchRowCommand.All:移至定義、在物件總管中選取、複製限定名稱),卡片、 快捷選單與預覽工具列照同一個順序建立,預覽的按下交回清單那一條路執行。沒有「在預覽中顯示」: 左鍵點一下就是預覽。預覽工具列只放 IsInPreview 的操作:複製限定名稱留在清單上,預覽上唯一的 複製是作用在畫面上那份定義的「複製定義」,隔一條群界線排在列操作之後,成功與失敗都送通知; 兩顆同圖示的複製並排只剩提示分得出來。定義內的 Ctrl+C 與右鍵選單照編輯器慣例只報失敗。
關掉重開記得什麼
只將比對位置、大小寫、全字存進 SqlAssistState;後兩項的格式是 TextMatchState, 與 SQL Memory 共用,未知格式整組回預設。 伺服器、資料庫與物件種類不保存,見搜尋範圍。
不支援
- 連結伺服器與四段式名稱。
- 指令碼內宣告的暫存表、資料表變數與 CTE。
- 資料庫與伺服器層級的 DDL 觸發程序:不在
sys.objects,也沒有物件總管上的結構描述節點可導航。 - 資料列內容;只搜尋名稱、結構與定義。
- regex、facet 語法與持久化索引。