2020-05-26 11:49:59 +00:00
using Microsoft.Search.Interop ;
2020-05-11 13:19:41 +00:00
namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
public class QueryConstructor
{
2020-06-08 04:20:22 +00:00
private readonly Settings settings ;
2020-05-11 13:19:41 +00:00
2020-05-11 20:47:45 +00:00
private const string SystemIndex = "SystemIndex" ;
2020-05-11 13:19:41 +00:00
public QueryConstructor ( Settings settings )
{
2020-06-08 04:20:22 +00:00
this . settings = settings ;
2020-05-11 13:19:41 +00:00
}
2020-05-11 20:47:45 +00:00
public CSearchQueryHelper CreateBaseQuery ( )
{
2020-05-18 11:31:28 +00:00
var baseQuery = CreateQueryHelper ( ) ;
2020-05-11 20:47:45 +00:00
// Set the number of results we want. Don't set this property if all results are needed.
2020-06-08 04:20:22 +00:00
baseQuery . QueryMaxResults = settings . MaxResult ;
2020-05-11 20:47:45 +00:00
// Set list of columns we want to display, getting the path presently
2020-08-23 22:21:16 +00:00
baseQuery . QuerySelectColumns = "System.FileName, System.ItemUrl, System.ItemType" ;
2020-05-11 20:47:45 +00:00
2020-05-18 11:31:28 +00:00
// Filter based on file name
2020-05-11 20:47:45 +00:00
baseQuery . QueryContentProperties = "System.FileName" ;
// Set sorting order
//baseQuery.QuerySorting = "System.ItemType DESC";
return baseQuery ;
}
2020-05-18 11:31:28 +00:00
internal CSearchQueryHelper CreateQueryHelper ( )
{
// This uses the Microsoft.Search.Interop assembly
var manager = new CSearchManager ( ) ;
// SystemIndex catalog is the default catalog in Windows
var catalogManager = manager . GetCatalog ( SystemIndex ) ;
// Get the ISearchQueryHelper which will help us to translate AQS --> SQL necessary to query the indexer
var queryHelper = catalogManager . GetQueryHelper ( ) ;
2021-01-23 02:53:01 +00:00
2020-05-18 11:31:28 +00:00
return queryHelper ;
}
2020-05-11 13:19:41 +00:00
///<summary>
2020-05-18 10:13:31 +00:00
/// Set the required WHERE clause restriction to search on the first level of a specified directory.
2020-05-11 13:19:41 +00:00
///</summary>
public string QueryWhereRestrictionsForTopLevelDirectorySearch ( string path )
{
2020-05-27 21:41:14 +00:00
var searchDepth = $"directory='file:" ;
2020-05-26 11:55:07 +00:00
2020-05-27 21:41:14 +00:00
return QueryWhereRestrictionsFromLocationPath ( path , searchDepth ) ;
}
///<summary>
/// Set the required WHERE clause restriction to search all files and subfolders of a specified directory.
///</summary>
public string QueryWhereRestrictionsForTopLevelDirectoryAllFilesAndFoldersSearch ( string path )
{
var searchDepth = $"scope='file:" ;
return QueryWhereRestrictionsFromLocationPath ( path , searchDepth ) ;
}
private string QueryWhereRestrictionsFromLocationPath ( string path , string searchDepth )
{
2020-05-28 11:35:12 +00:00
if ( path . EndsWith ( Constants . DirectorySeperator ) )
2020-05-27 21:41:14 +00:00
return searchDepth + $"{path}'" ;
2020-05-26 11:55:07 +00:00
2020-05-28 11:35:12 +00:00
var indexOfSeparator = path . LastIndexOf ( Constants . DirectorySeperator ) ;
2020-05-26 11:55:07 +00:00
var itemName = path . Substring ( indexOfSeparator + 1 ) ;
2020-05-28 11:35:12 +00:00
if ( itemName . StartsWith ( Constants . AllFilesFolderSearchWildcard ) )
2020-05-27 21:41:14 +00:00
itemName = itemName . Substring ( 1 ) ;
2020-05-26 11:55:07 +00:00
var previousLevelDirectory = path . Substring ( 0 , indexOfSeparator ) ;
2020-05-27 21:41:14 +00:00
if ( string . IsNullOrEmpty ( itemName ) )
2021-01-23 02:53:01 +00:00
return $"{searchDepth}{previousLevelDirectory}'{QueryOrderByFileNameRestriction}" ;
2020-05-27 21:41:14 +00:00
2021-01-23 02:53:01 +00:00
return $"(System.FileName LIKE '{itemName}%' OR CONTAINS(System.FileName,'\" { itemName } * \ "',1033)) AND {searchDepth}{previousLevelDirectory}' {QueryOrderByFileNameRestriction}" ;
2020-05-11 13:19:41 +00:00
}
2020-05-18 10:13:31 +00:00
///<summary>
/// Search will be performed on all folders and files on the first level of a specified directory.
///</summary>
2020-05-26 11:49:59 +00:00
public string QueryForTopLevelDirectorySearch ( string path )
2020-05-11 20:50:17 +00:00
{
2020-06-08 04:20:22 +00:00
string query = "SELECT TOP " + settings . MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE " ;
2020-05-11 20:50:17 +00:00
2020-05-28 11:35:12 +00:00
if ( path . LastIndexOf ( Constants . AllFilesFolderSearchWildcard ) > path . LastIndexOf ( Constants . DirectorySeperator ) )
2020-05-27 21:41:14 +00:00
return query + QueryWhereRestrictionsForTopLevelDirectoryAllFilesAndFoldersSearch ( path ) ;
2020-05-11 20:50:17 +00:00
2021-01-23 02:53:01 +00:00
return query + QueryWhereRestrictionsForTopLevelDirectorySearch ( path ) + QueryOrderByFileNameRestriction ;
2020-05-11 20:50:17 +00:00
}
2020-05-18 10:14:38 +00:00
///<summary>
/// Search will be performed on all folders and files based on user's search keywords.
///</summary>
public string QueryForAllFilesAndFolders ( string userSearchString )
{
2020-05-18 11:31:28 +00:00
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
2021-01-23 02:53:01 +00:00
return CreateBaseQuery ( ) . GenerateSQLFromUserQuery ( userSearchString ) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
+ QueryOrderByFileNameRestriction ;
2020-05-18 10:14:38 +00:00
}
///<summary>
/// Set the required WHERE clause restriction to search for all files and folders.
///</summary>
2021-01-23 02:53:01 +00:00
public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'" ;
public const string QueryOrderByFileNameRestriction = " ORDER BY System.FileName" ;
2020-07-12 12:43:38 +00:00
///<summary>
/// Search will be performed on all indexed file contents for the specified search keywords.
///</summary>
public string QueryForFileContentSearch ( string userSearchString )
{
string query = "SELECT TOP " + settings . MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE " ;
2021-01-23 02:53:01 +00:00
return query + QueryWhereRestrictionsForFileContentSearch ( userSearchString ) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
+ QueryOrderByFileNameRestriction ;
2020-07-12 12:43:38 +00:00
}
///<summary>
/// Set the required WHERE clause restriction to search within file content.
///</summary>
public string QueryWhereRestrictionsForFileContentSearch ( string searchQuery )
{
return $"FREETEXT('{searchQuery}')" ;
}
2020-05-11 13:19:41 +00:00
}
}