(sortBy field_sort . map fst $ Map.elems groupFieldsMap)
(sortBy field_sort fdefs)
+
+-- | Tests that requested names checking behaves as expected.
+prop_getRequestedNames :: Property
+prop_getRequestedNames =
+ forAll getName $ \node1 ->
+ let chk = getRequestedNames . Query QRNode []
+ q_node1 = QuotedString node1
+ eq_name = EQFilter "name"
+ eq_node1 = eq_name q_node1
+ in conjoin [ printTestCase "empty filter" $ chk EmptyFilter ==? []
+ , printTestCase "and filter" $ chk (AndFilter [eq_node1]) ==? []
+ , printTestCase "simple equality" $ chk eq_node1 ==? [node1]
+ , printTestCase "non-name field" $
+ chk (EQFilter "foo" q_node1) ==? []
+ , printTestCase "non-simple filter" $
+ chk (OrFilter [ eq_node1 , LTFilter "foo" q_node1]) ==? []
+ ]
+
testSuite "Query/Query"
[ 'prop_queryNode_noUnknown
, 'prop_queryNode_Unknown
, 'prop_queryGroup_Unknown
, 'prop_queryGroup_types
, 'case_queryGroup_allfields
+ , 'prop_getRequestedNames
]
module Ganeti.Query.Filter
( compileFilter
, evaluateFilter
+ , requestedNames
) where
import Control.Applicative
+import Control.Monad (liftM)
import qualified Data.Map as Map
import Data.Traversable (traverse)
import Text.JSON (JSValue(..), fromJSString)
maybe Nothing (\rt' -> Just $ getter rt' item) rt
tryGetter _ _ _ FieldUnknown = Just $
ResultEntry RSUnknown Nothing
+
+-- | Computes the requested names, if only names were requested (and
+-- with equality). Otherwise returns 'Nothing'.
+requestedNames :: FilterField -> Filter FilterField -> Maybe [FilterValue]
+requestedNames _ EmptyFilter = Just []
+requestedNames namefield (OrFilter flts) =
+ liftM concat $ mapM (requestedNames namefield) flts
+requestedNames namefield (EQFilter fld val) =
+ if namefield == fld
+ then Just [val]
+ else Nothing
+requestedNames _ _ = Nothing
( query
, queryFields
+ , getRequestedNames
) where
import Control.Monad (filterM)
FieldRuntime _ -> True
_ -> False)
+-- | Checks whether we have requested exactly some names. This is a
+-- simple wrapper over 'requestedNames' and 'nameField'.
+needsNames :: Query -> Maybe [FilterValue]
+needsNames (Query kind _ qfilter) = requestedNames (nameField kind) qfilter
+
+-- | Computes the name field for different query types.
+nameField :: ItemType -> FilterField
+nameField QRJob = "id"
+nameField _ = "name"
+
+-- | Extracts all quoted strings from a list, ignoring the
+-- 'NumericValue' entries.
+getAllQuotedStrings :: [FilterValue] -> [String]
+getAllQuotedStrings =
+ concatMap extractor
+ where extractor (NumericValue _) = []
+ extractor (QuotedString val) = [val]
+
+-- | Checks that we have either requested a valid set of names, or we
+-- have a more complex filter.
+getRequestedNames :: Query -> [String]
+getRequestedNames qry =
+ case needsNames qry of
+ Just names -> getAllQuotedStrings names
+ Nothing -> []
+
-- | Main query execution function.
query :: ConfigData -- ^ The current configuration
-> Bool -- ^ Whether to collect live data