Skip to content
This repository has been archived by the owner on Apr 10, 2018. It is now read-only.

Allow null as a filter operand #421

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions docs/_generate/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,15 @@ <h3 class='space-bottom1'><a href='#types-filter' title='link to filter'>Filter<
<div class='space-bottom1'>
<code>["!in", <var>key</var>, <var>v0</var>, ..., <var>vn</var>]</code> <span class='quiet pad1x strong small'>set exclusion: <var>key</var> ∉ {<var>v0</var>, ..., <var>vn</var>}</span>
</div>
<div class='space-bottom1'>
<code>["has", <var>key</var>]</code></span> <span class='quiet pad1x strong small'><var>key</var> exists on feature</span>
</div>
<div class='space-bottom1'>
<code>["!has", <var>key</var>]</code></span> <span class='quiet pad1x strong small'><var>key</var> does not exist on feature</span>
</div>
<div class='space-bottom1'>
<code>["!in", <var>key</var>, <var>v0</var>, ..., <var>vn</var>]</code> <span class='quiet pad1x strong small'>set exclusion: <var>key</var> ∉ {<var>v0</var>, ..., <var>vn</var>}</span>
</div>
<div class='space-bottom1'>
<code>["all", <var>f0</var>, ..., <var>fn</var>]</code> <span class='quiet pad1x strong small'>logical <code>AND</code>: <var>f0</var> ∧ ... ∧ <var>fn</var></span>
</div>
Expand All @@ -638,8 +647,8 @@ <h3 class='space-bottom1'><a href='#types-filter' title='link to filter'>Filter<
<p>
A filter's <var>key</var> must be a string that identifies a feature property, or
the special key <code>"$type"</code>, which identifies the feature type. A <var>value</var>
(and <var>v0</var>, ..., <var>vn</var> for set operators) must be a <a href="#string">string</a>,
<a href="#number">number</a>, or <a href="#boolean">boolean</a> to compare the property value
(and <var>v0</var>, ..., <var>vn</var> for set operators) must be a <a href="#types-string">string</a>,
a <a href="#types-number">number</a>, a <a href="#types-boolean">boolean</a>, or <code>null</code> to compare the property value
against. For the <code>"$type"</code> key it must be one of <code>"Point"</code>,
<code>"LineString"</code>, or <code>"Polygon"</code>.
</p>
Expand Down
81 changes: 52 additions & 29 deletions lib/validate/validate_filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ module.exports = function validateFilter(options) {
var value = options.value;
var key = options.key;
var styleSpec = options.styleSpec;
var type;

var errors = [];

Expand Down Expand Up @@ -37,54 +36,78 @@ module.exports = function validateFilter(options) {
if (value.length >= 2 && value[1] == '$type') {
errors.push(new ValidationError(key, value, '"$type" cannot be use with operator "%s"', value[0]));
}
/* falls through */
if (value.length != 3) {
errors.push(new ValidationError(key, value, 'filter array for operator "%s" must have 3 elements', value[0]));
}
return errors.concat(validateSimpleFilter(options));

case '==':
case '!=':
if (value.length != 3) {
errors.push(new ValidationError(key, value, 'filter array for operator "%s" must have 3 elements', value[0]));
}
/* falls through */
return errors.concat(validateSimpleFilter(options));

case 'in':
case '!in':
if (value.length >= 2) {
type = getType(value[1]);
if (type !== 'string') {
errors.push(new ValidationError(key + '[1]', value[1], 'string expected, %s found', type));
} else if (value[1][0] === '@') {
errors.push(new ValidationError(key + '[1]', value[1], 'filter key cannot be a constant'));
}
}
for (var i = 2; i < value.length; i++) {
type = getType(value[i]);
if (value[1] == '$type') {
errors = errors.concat(validateEnum({
key: key + '[' + i + ']',
value: value[i],
valueSpec: styleSpec.geometry_type,
style: options.style,
styleSpec: options.styleSpec
}));
} else if (type === 'string' && value[i][0] === '@') {
errors.push(new ValidationError(key + '[' + i + ']', value[i], 'filter value cannot be a constant'));
} else if (type !== 'string' && type !== 'number' && type !== 'boolean') {
errors.push(new ValidationError(key + '[' + i + ']', value[i], 'string, number, or boolean expected, %s found', type));
}
return errors.concat(validateSimpleFilter(options));

case 'has':
case '!has':
if (value.length != 2) {
errors.push(new ValidationError(key, value, '"has" filter must have exactly 1 operand'));
}
break;
return errors.concat(validateSimpleFilter(options));

case 'any':
case 'all':
case 'none':
for (i = 1; i < value.length; i++) {
for (var i = 1; i < value.length; i++) {
errors = errors.concat(validateFilter({
key: key + '[' + i + ']',
value: value[i],
style: options.style,
styleSpec: options.styleSpec
}));
}
break;
return errors;
}

return errors;
};

function validateSimpleFilter(options) {
var value = options.value;
var key = options.key;
var styleSpec = options.styleSpec;
var errors = [];
var type;

if (value.length >= 2) {
type = getType(value[1]);
if (type !== 'string') {
errors.push(new ValidationError(key + '[1]', value[1], 'string expected, %s found', type));
} else if (value[1][0] === '@') {
errors.push(new ValidationError(key + '[1]', value[1], 'filter key cannot be a constant'));
}
}

for (var i = 2; i < value.length; i++) {
type = getType(value[i]);
if (value[1] == '$type') {
errors = errors.concat(validateEnum({
key: key + '[' + i + ']',
value: value[i],
valueSpec: styleSpec.geometry_type,
style: options.style,
styleSpec: options.styleSpec
}));
} else if (type === 'string' && value[i][0] === '@') {
errors.push(new ValidationError(key + '[' + i + ']', value[i], 'filter value cannot be a constant'));
} else if (type !== 'string' && type !== 'number' && type !== 'boolean' && value[i] !== null) {
errors.push(new ValidationError(key + '[' + i + ']', value[i], 'string, number, boolean, or null expected, %s found', type));
}
}

return errors;
}
4 changes: 3 additions & 1 deletion reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,9 @@
"!in",
"all",
"any",
"none"
"none",
"has",
"!has"
],
"doc": "The filter operator."
},
Expand Down
Loading