-
Proposal:
Hide
In the following rules null means either a null literal or a null value
null eq null is true
null ne null is false
notnull eq null is false
notnull ne null is true
null le null is true --> mathematically consistent with the preceding rules and how JavaScript and Python work, but differs from C# and SQL
null ge null is true --> mathematically consistent with the preceding rules and how JavaScript and Python work, but differs from C# and SQL
notnull le null is false
notnull ge null is false
null le notnull is false
null ge notnull is false
null lt null is false
null gt null is false
notnull lt null is false
notnull gt null is false
null lt notnull is false
null gt notnull is false
null in logical operators is treated as unknown, see Kleene logic:
null and null is null
null and false is false
null and true is null
null or null is null
null or true is true
null or false is null
not null is null
$filter only returns items where the expression evaluates to true and omits items where it evaluates to false or to null
Show
In the following rules null means either a null literal or a null value
null eq null is true
null ne null is false
notnull eq null is false
notnull ne null is true
null le null is true --> mathematically consistent with the preceding rules and how JavaScript and Python work, but differs from C# and SQL
null ge null is true --> mathematically consistent with the preceding rules and how JavaScript and Python work, but differs from C# and SQL
notnull le null is false
notnull ge null is false
null le notnull is false
null ge notnull is false
null lt null is false
null gt null is false
notnull lt null is false
notnull gt null is false
null lt notnull is false
null gt notnull is false
null in logical operators is treated as unknown, see Kleene logic:
null and null is null
null and false is false
null and true is null
null or null is null
null or true is true
null or false is null
not null is null
$filter only returns items where the expression evaluates to true and omits items where it evaluates to false or to null
-
Resolution:
Show
https://www.oasis-open.org/committees/download.php/49613/odata-v4.0-wd02-part1-protocol-2013-06-19.docx
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/vocabularies/Org.OData.Core.V1.xml?rev=377
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/vocabularies/Org.OData.Capabilities.V1.xml?rev=379
https://www.oasis-open.org/committees/download.php/49614/odata-v4.0-wd02-part2-url-conventions-2013-06-19.docx
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/ABNF/odata-abnf-construction-rules.txt?rev=380
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/ABNF/odata-abnf-testcases.xml?rev=380
https://www.oasis-open.org/committees/download.php/49615/odata-v4.0-wd02-part3-csdl-2013-06-19.docx
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/schemas/edmx.xsd?rev=357
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/schemas/edm.xsd?rev=377
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/schemas/MetadataService.edmx?rev=374
https://www.oasis-open.org/committees/download.php/49611/odata-atom-format-v4.0-wd02-2013-06-19.docx
https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/schemas/metadata.xsd?rev=382
https://www.oasis-open.org/committees/download.php/49612/odata-json-format-v4.0-wd02-2013-06-19.docx
I didn't see any mention of lifted operators in the working drafts. We should define how each operator behaves when one (or both) operands is null.
With that said, the V3 spec (section 2.2.3.6.1.1.5) is inconsistent with it's treatment of null:
- For equality operators, null eq null is true and null eq <anything not null> is false (i.e. the result is true or false)
- Any relational operators when compared with null are false (i.e. the result is true or false)
- This implies that null ge null and null le null is false which is inconsistent with null eq null is true
- Logical operators treat null as false (i.e. the result is true or false)
- Unary operators are null if the operand is null (i.e. in the case of not, the result is true, false, or null)
{"report":{"apdex":1,"isInitial":true,"journeyId":"24acefd3-6174-46ef-ab1b-3662167b59fd","key":"jira.project.issue.view-issue","navigationType":0,"readyForUser":777.5,"redirectCount":0,"resourceLoadedEnd":740.1999998092651,"resourceLoadedStart":214.19999980926514,"resourceTiming":[{"duration":201.90000009536743,"initiatorType":"link","name":"https://issues.oasis-open.org/s/3edeca31ab9ba77980aae0809fbe7121-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/0a4716d29b2d5b1bdcdb168b4efc119e/_/download/contextbatch/css/_super/batch.css","startTime":214.19999980926514,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":214.19999980926514,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":416.09999990463257,"responseStart":0,"secureConnectionStart":0},{"duration":201.7000002861023,"initiatorType":"link","name":"https://issues.oasis-open.org/s/7d2823769c2e7b66e860863fe879b7f8-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/9aebb1c0aaa4c36289529757ec9dbb54/_/download/contextbatch/css/project.issue.navigator,jira.view.issue,jira.global,atl.general,-_super/batch.css?agile_global_admin_condition=true&jag=true&jira.create.linked.issue=true&richediton=true","startTime":214.69999980926514,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":214.69999980926514,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":416.40000009536743,"responseStart":0,"secureConnectionStart":0},{"duration":201.59999990463257,"initiatorType":"link","name":"https://issues.oasis-open.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/8.0.5/_/download/batch/com.atlassian.auiplugin:split_aui.pattern.label/com.atlassian.auiplugin:split_aui.pattern.label.css","startTime":214.90000009536743,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":214.90000009536743,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":416.5,"responseStart":0,"secureConnectionStart":0},{"duration":201.59999990463257,"initiatorType":"link","name":"https://issues.oasis-open.org/s/645acc233eb869f48a571293b8358a7d-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/1.0/_/download/batch/jira.webresources:global-static-adgs/jira.webresources:global-static-adgs.css","startTime":215.09999990463257,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":215.09999990463257,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":416.69999980926514,"responseStart":0,"secureConnectionStart":0},{"duration":202.89999961853027,"initiatorType":"link","name":"https://issues.oasis-open.org/s/a0dd6509771c1de0667aae5429c04cda-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/1.0/_/download/batch/jira.webresources:global-static/jira.webresources:global-static.css","startTime":215.30000019073486,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":215.30000019073486,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":418.19999980926514,"responseStart":0,"secureConnectionStart":0},{"duration":242.30000019073486,"initiatorType":"script","name":"https://issues.oasis-open.org/s/e5479157e7a0c08b005e6522f2f04104-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/0a4716d29b2d5b1bdcdb168b4efc119e/_/download/contextbatch/js/_super/batch.js?locale=en-US","startTime":215.5,"connectEnd":215.5,"connectStart":215.5,"domainLookupEnd":215.5,"domainLookupStart":215.5,"fetchStart":215.5,"redirectEnd":0,"redirectStart":0,"requestStart":215.5,"responseEnd":457.80000019073486,"responseStart":457.80000019073486,"secureConnectionStart":215.5},{"duration":269.59999990463257,"initiatorType":"script","name":"https://issues.oasis-open.org/s/83514d5d4e8543747b02042eafcdc99c-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/9aebb1c0aaa4c36289529757ec9dbb54/_/download/contextbatch/js/project.issue.navigator,jira.view.issue,jira.global,atl.general,-_super/batch.js?agile_global_admin_condition=true&jag=true&jira.create.linked.issue=true&locale=en-US&richediton=true","startTime":216.09999990463257,"connectEnd":216.09999990463257,"connectStart":216.09999990463257,"domainLookupEnd":216.09999990463257,"domainLookupStart":216.09999990463257,"fetchStart":216.09999990463257,"redirectEnd":0,"redirectStart":0,"requestStart":216.09999990463257,"responseEnd":485.69999980926514,"responseStart":485.69999980926514,"secureConnectionStart":216.09999990463257},{"duration":271.59999990463257,"initiatorType":"script","name":"https://issues.oasis-open.org/s/70bb2263e59e7e1f04fbd137c80b895b-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/aae1242f5fc81cc6a5bb8bc963ccda29/_/download/contextbatch/js/atl.global,-_super/batch.js?locale=en-US","startTime":216.30000019073486,"connectEnd":216.30000019073486,"connectStart":216.30000019073486,"domainLookupEnd":216.30000019073486,"domainLookupStart":216.30000019073486,"fetchStart":216.30000019073486,"redirectEnd":0,"redirectStart":0,"requestStart":216.30000019073486,"responseEnd":487.90000009536743,"responseStart":487.90000009536743,"secureConnectionStart":216.30000019073486},{"duration":271.80000019073486,"initiatorType":"script","name":"https://issues.oasis-open.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/1.0/_/download/batch/jira.webresources:calendar-en/jira.webresources:calendar-en.js","startTime":216.5,"connectEnd":216.5,"connectStart":216.5,"domainLookupEnd":216.5,"domainLookupStart":216.5,"fetchStart":216.5,"redirectEnd":0,"redirectStart":0,"requestStart":216.5,"responseEnd":488.30000019073486,"responseStart":488.30000019073486,"secureConnectionStart":216.5},{"duration":272,"initiatorType":"script","name":"https://issues.oasis-open.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/1.0/_/download/batch/jira.webresources:calendar-localisation-moment/jira.webresources:calendar-localisation-moment.js","startTime":216.69999980926514,"connectEnd":216.69999980926514,"connectStart":216.69999980926514,"domainLookupEnd":216.69999980926514,"domainLookupStart":216.69999980926514,"fetchStart":216.69999980926514,"redirectEnd":0,"redirectStart":0,"requestStart":216.69999980926514,"responseEnd":488.69999980926514,"responseStart":488.69999980926514,"secureConnectionStart":216.69999980926514},{"duration":272.19999980926514,"initiatorType":"script","name":"https://issues.oasis-open.org/s/cda37faab827dbdf305de8efe8282062-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/8.0.5/_/download/batch/com.atlassian.auiplugin:split_aui.pattern.label/com.atlassian.auiplugin:split_aui.pattern.label.js?locale=en-US","startTime":216.90000009536743,"connectEnd":216.90000009536743,"connectStart":216.90000009536743,"domainLookupEnd":216.90000009536743,"domainLookupStart":216.90000009536743,"fetchStart":216.90000009536743,"redirectEnd":0,"redirectStart":0,"requestStart":216.90000009536743,"responseEnd":489.09999990463257,"responseStart":489.09999990463257,"secureConnectionStart":216.90000009536743},{"duration":381.5,"initiatorType":"link","name":"https://issues.oasis-open.org/s/07245784f53abc49bad9d9d4d36c577a-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/cadc4f20cc5c138dee060d42cf85f220/_/download/contextbatch/css/jira.global.look-and-feel,-_super/batch.css","startTime":217,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":217,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":598.5,"responseStart":0,"secureConnectionStart":0},{"duration":272.2000002861023,"initiatorType":"script","name":"https://issues.oasis-open.org/rest/api/1.0/shortcuts/803004/a29179d70fa8562374ee16707692af77/shortcuts.js?context=issuenavigation&context=issueaction","startTime":217.19999980926514,"connectEnd":217.19999980926514,"connectStart":217.19999980926514,"domainLookupEnd":217.19999980926514,"domainLookupStart":217.19999980926514,"fetchStart":217.19999980926514,"redirectEnd":0,"redirectStart":0,"requestStart":217.19999980926514,"responseEnd":489.40000009536743,"responseStart":489.40000009536743,"secureConnectionStart":217.19999980926514},{"duration":346.69999980926514,"initiatorType":"link","name":"https://issues.oasis-open.org/s/f77fd89aa211a76b20e9b0e63564383c-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/4a9288299d147101bf66484f4be48925/_/download/contextbatch/css/com.atlassian.jira.projects.sidebar.init,-_super,-jira.view.issue,-project.issue.navigator/batch.css?jira.create.linked.issue=true&richediton=true","startTime":252,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":252,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":598.6999998092651,"responseStart":0,"secureConnectionStart":0},{"duration":238.80000019073486,"initiatorType":"script","name":"https://issues.oasis-open.org/s/41525c48ddceeb9b11e54085268fc285-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/4a9288299d147101bf66484f4be48925/_/download/contextbatch/js/com.atlassian.jira.projects.sidebar.init,-_super,-jira.view.issue,-project.issue.navigator/batch.js?jira.create.linked.issue=true&locale=en-US&richediton=true","startTime":252.19999980926514,"connectEnd":252.19999980926514,"connectStart":252.19999980926514,"domainLookupEnd":252.19999980926514,"domainLookupStart":252.19999980926514,"fetchStart":252.19999980926514,"redirectEnd":0,"redirectStart":0,"requestStart":252.19999980926514,"responseEnd":491,"responseStart":491,"secureConnectionStart":252.19999980926514},{"duration":439.09999990463257,"initiatorType":"script","name":"https://issues.oasis-open.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/1.0/_/download/batch/jira.webresources:bigpipe-js/jira.webresources:bigpipe-js.js","startTime":262.5,"connectEnd":262.5,"connectStart":262.5,"domainLookupEnd":262.5,"domainLookupStart":262.5,"fetchStart":262.5,"redirectEnd":0,"redirectStart":0,"requestStart":262.5,"responseEnd":701.5999999046326,"responseStart":701.5999999046326,"secureConnectionStart":262.5},{"duration":456.5,"initiatorType":"script","name":"https://issues.oasis-open.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/nu8zej/803004/aeedb5937bed650f2f0cc4ec9ceaa5d3/1.0/_/download/batch/jira.webresources:bigpipe-init/jira.webresources:bigpipe-init.js","startTime":283.69999980926514,"connectEnd":283.69999980926514,"connectStart":283.69999980926514,"domainLookupEnd":283.69999980926514,"domainLookupStart":283.69999980926514,"fetchStart":283.69999980926514,"redirectEnd":0,"redirectStart":0,"requestStart":283.69999980926514,"responseEnd":740.1999998092651,"responseStart":740.1999998092651,"secureConnectionStart":283.69999980926514},{"duration":98.2000002861023,"initiatorType":"xmlhttprequest","name":"https://issues.oasis-open.org/rest/webResources/1.0/resources","startTime":609.0999999046326,"connectEnd":609.0999999046326,"connectStart":609.0999999046326,"domainLookupEnd":609.0999999046326,"domainLookupStart":609.0999999046326,"fetchStart":609.0999999046326,"redirectEnd":0,"redirectStart":0,"requestStart":609.0999999046326,"responseEnd":707.3000001907349,"responseStart":707.3000001907349,"secureConnectionStart":609.0999999046326}],"threshold":1000,"fetchStart":0,"domainLookupStart":105,"domainLookupEnd":105,"connectStart":105,"connectEnd":156,"secureConnectionStart":130,"requestStart":156,"responseStart":206,"responseEnd":283,"domLoading":209,"domInteractive":879,"domContentLoadedEventStart":879,"domContentLoadedEventEnd":928,"domComplete":1094,"loadEventStart":1094,"loadEventEnd":1098,"userAgent":"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)","marks":[],"measures":[],"correlationId":"efcc2a723485eb","effectiveType":"4g","downlink":9.9,"rtt":0,"serverDuration":97,"dbReadsTimeInMs":11,"dbConnsTimeInMs":13,"applicationHash":"4d4040e0714d65b7fffa4801569d014c0b16eaa9","experiments":[]}}
I 100% agree with that; 3-value logic definitely complicates things. And if one of the goals of OData is to keep things simple, 3-value logic is probably not the correct approach to take.
I am definitely fine with using 2-value logic as long as we make the results consistent. In which case I still think proposal 1) from the post on "16/Dec/12 04:47 PM" has the most consistent treatment of nulls and simplest to understand.