Permalink
Browse files

Merge pull request #36 from ohad/master

Adding a HAS condition to WHERE statements
  • Loading branch information...
2 parents d3e98c3 + 9187264 commit 5e3b063106fa85938ef51ce8184b1b7b6674c1a4 @jgm committed Oct 4, 2013
Showing with 19 additions and 9 deletions.
  1. +9 −5 README.markdown
  2. +9 −4 Yst/Data.hs
  3. +1 −0 Yst/Types.hs
View
@@ -279,17 +279,21 @@ of lists of lists, and so on.
> Selects only items that meet a condition.
-> A *condition* in a `WHERE` statement is a Boolean combination (using
+> A *condition* in a `WHERE` statement is a Boolean combination (using
`NOT`, `AND`, `OR`, and parentheses for disambiguation) of *basic
-conditions*. A *basic condition* is of the form `value op value`,
-where `value` may be either a fieldname or a constant. Note that
-all constants must be enclosed in quotes. `op` may be one of the
-following: `=`, `>=`, `<=`, `>`, `<` and 'contains'.
+conditions*. A *basic condition* is either of the form `value op
+value`, where `value` may be either a fieldname or a constant, or of
+the form `HAS fieldname' where `fieldname' is a string constant. Note
+that all constants must be enclosed in quotes. `op` may be one of the
+following: `=`, `>=`, `<=`, `>`, `<` and 'contains'.
> The basic condition `arg1 contains arg2` succeeds if and only if
`arg1` is a fieldname whose value is a list containing the value of
`arg2`.
+> The basic condition `HAS fieldname' succeeds if and only if the item
+has the fieldname as a field. For example, `HAS "data"'.
+
Note that the order of transformations is significant. You can get
different results if you use `LIMIT` before or after `ORDER BY`,
for example.
View
@@ -77,9 +77,11 @@ applyDataOption (NList ns) (OrderBy xs) =
applyDataOption _ _ = error "order by and group by can be used only on lists"
satisfiesCond :: FilterCond -> Node -> Bool
-satisfiesCond (And c1 c2) n = satisfiesCond c1 n && satisfiesCond c2 n
-satisfiesCond (Or c1 c2) n = satisfiesCond c1 n || satisfiesCond c2 n
-satisfiesCond (Not c1) n = not (satisfiesCond c1 n)
+satisfiesCond (And c1 c2) n = satisfiesCond c1 n && satisfiesCond c2 n
+satisfiesCond (Or c1 c2) n = satisfiesCond c1 n || satisfiesCond c2 n
+satisfiesCond (Not c1) n = not (satisfiesCond c1 n)
+satisfiesCond (Has s) (NMap ns) = elem s (map fst ns)
+satisfiesCond (Has _) _ = False
satisfiesCond (Filter test arg1 arg2) n =
(filterTestPred test) (filterArgToNode arg1 n) (filterArgToNode arg2 n)
@@ -221,7 +223,7 @@ pOptWhere = try $ do
return $ Where cond
pBooleanCondition :: GenParser Char st FilterCond
-pBooleanCondition = spaces >> (pNot <|> pAnd <|> pOr <|> pInParens pBooleanCondition <|> pBasicCond)
+pBooleanCondition = spaces >> ( pHas <|> pNot <|> pAnd <|> pOr <|> pInParens pBooleanCondition <|> pBasicCond)
pInParens :: GenParser Char st a -> GenParser Char st a
pInParens innerParser = try $ do
@@ -235,6 +237,9 @@ pInParens innerParser = try $ do
pNot :: GenParser Char st FilterCond
pNot = try $ pString "not" >> pSpace >> liftM Not pBooleanCondition
+pHas :: GenParser Char st FilterCond
+pHas = try $ pString "has" >> pSpace >> liftM Has (pQuoted '"' <|> pQuoted '\'')
+
pAnd :: GenParser Char st FilterCond
pAnd = try $ do
x <- pNot <|> pInParens pBooleanCondition <|> pBasicCond
View
@@ -70,6 +70,7 @@ data FilterCond = Filter FilterTest FilterArg FilterArg
| And FilterCond FilterCond
| Or FilterCond FilterCond
| Not FilterCond
+ | Has String
deriving (Show, Read, Eq)
data FilterArg = AttrValue String

0 comments on commit 5e3b063

Please sign in to comment.