[stcheck] fix visit_constant checker: a etype inside a CAST is a good thing
Actually, if you put a CAST after a relation (!= ``is`` or ``is_instance_of``),
the checker raises an error saying that the etype (inside the CAST) must be
after a ``is`` or ``is_instance_of`` relation. In fact the CAST case was tested too late.
This allow to use CAST outside the selection section, so:
Closes #79232
--- a/stcheck.py Fri Jun 06 13:27:31 2014 +0200
+++ b/stcheck.py Thu Apr 24 15:46:19 2014 +0200
@@ -457,18 +457,18 @@
pass
def visit_constant(self, constant, state):
- #assert len(constant.children)==0
- if constant.type == 'etype':
- if constant.value not in self.schema:
- state.error('unknown entity type %s' % constant.value)
- rel = constant.relation()
- if rel is not None:
- if rel.r_type not in ('is', 'is_instance_of'):
- msg ='using an entity type in only allowed with "is" relation'
- state.error(msg)
- elif not (isinstance(constant.parent, Function) and
- constant.parent.name == 'CAST'):
- state.error('Entity types can only be used inside a CAST()')
+ if constant.type != 'etype':
+ return
+ if constant.value not in self.schema:
+ state.error('unknown entity type %s' % constant.value)
+ if (isinstance(constant.parent, Function) and
+ constant.parent.name == 'CAST'):
+ return
+ rel = constant.relation()
+ if rel is not None and rel.r_type in ('is', 'is_instance_of'):
+ return
+ state.error('Entity types can only be used inside a CAST() '
+ 'or with "is" relation')
def leave_constant(self, node, state):
pass
--- a/test/unittest_analyze.py Fri Jun 06 13:27:31 2014 +0200
+++ b/test/unittest_analyze.py Thu Apr 24 15:46:19 2014 +0200
@@ -548,5 +548,22 @@
self.assertEqual(sols, [{'U': 'Person'}])
+ def test_selection_with_cast(self):
+ node = self.helper.parse('Any X WHERE X name CAST(String, E), Y eid E, X owned_by Y')
+ self.helper.compute_solutions(node, debug=DEBUG)
+ sols = sorted(node.children[0].solutions)
+ self.assertEqual(sols, [{'E': 'Int', 'X': 'Company', 'Y': 'Person'},
+ {'E': 'Int', 'X': 'Person', 'Y': 'Person'},
+ {'E': 'Int', 'X': 'Student', 'Y': 'Person'}])
+
+ def test_set_with_cast(self):
+ node = self.helper.parse('SET X name CAST(String, E), X work_for Y WHERE Y eid E')
+ self.helper.compute_solutions(node, debug=DEBUG)
+ sols = sorted(node.solutions)
+ self.assertEqual(sols, [{'X': 'Person', 'Y': 'Company', 'E': 'Int'},
+ {'X': 'Student', 'Y': 'Company', 'E': 'Int'}])
+
+
+
if __name__ == '__main__':
unittest_main()
--- a/test/unittest_stcheck.py Fri Jun 06 13:27:31 2014 +0200
+++ b/test/unittest_stcheck.py Thu Apr 24 15:46:19 2014 +0200
@@ -80,11 +80,10 @@
# variable with only ?1 cardinality
'DISTINCT Any P ORDERBY PN WHERE P work_for X, P name PN',
'DISTINCT Any P ORDERBY XN WHERE P work_for X, X name XN',
-
'Any X WHERE X eid > 0, X eid < 42',
'Any X WHERE X eid 1, X eid < 42',
-
-
+ 'Any X WHERE X number CAST(Int, Y), X name Y',
+ 'SET X number CAST(Int, Y) WHERE X name Y',
)
class CheckClassTest(TestCase):