def testLet(self): self.assertEqual( solve.solve( ast.Let(ast.Bind(ast.Pair(ast.Literal("x"), ast.Literal(5))), ast.Sum(ast.Var("x"), ast.Var("x"))), {}).value, [10]) # Previous binding should be made available to subsequent bindings. self.assertEqual( solve.solve( ast.Let( ast.Bind( ast.Pair(ast.Literal("x"), ast.Literal(5)), ast.Pair(ast.Literal("y"), ast.Sum(ast.Var("x"), ast.Literal(5)))), ast.Var("y")), {}).value, [10])
def let(self): saved_start = self.tokens.matched.start expect_rparens = 0 while self.tokens.accept(common_grammar.lparen): expect_rparens += 1 bindings = [] while True: symbol = self.tokens.expect(common_grammar.symbol) binding = ast.Literal(symbol.value, start=symbol.start, end=symbol.end, source=self.original) self.tokens.expect(grammar.let_assign) value = self.expression() bindings.append(ast.Pair(binding, value, start=binding.start, end=value.end, source=self.original)) if not self.tokens.accept(common_grammar.comma): break bind = ast.Bind(*bindings, start=bindings[0].start, end=bindings[-1].end, source=self.original) while expect_rparens: self.tokens.expect(common_grammar.rparen) expect_rparens -= 1 nested_expression = self.expression() return ast.Let(bind, nested_expression, start=saved_start, end=nested_expression.end, source=self.original)
def testComplexSelect(self): query = ("(SELECT proc.parent.pid AS ppid, proc.pid FROM pslist(10) " "WHERE COUNT(proc.open_files) > 10) and True") expected = ast.Intersection( ast.Map( ast.Filter( ast.Apply(ast.Var("pslist"), ast.Literal(10)), ast.StrictOrderedSet( ast.Apply( ast.Var("COUNT"), ast.Resolve(ast.Var("proc"), ast.Literal("open_files"))), ast.Literal(10))), ast.Bind( ast.Pair( ast.Literal("ppid"), ast.Resolve( ast.Resolve(ast.Var("proc"), ast.Literal("parent")), ast.Literal("pid"))), ast.Pair(ast.Literal("pid"), ast.Resolve(ast.Var("proc"), ast.Literal("pid"))))), ast.Literal(True)) self.assertQueryMatches(query, expected)
def testSelectWhat(self): self.assertQueryMatches( "SELECT proc.parent.pid AS ppid," "proc.pid," "'foo'," "asdate(proc.starttime)," "proc.fd[5]" "FROM pslist()", ast.Map( ast.Apply(ast.Var("pslist")), ast.Bind( ast.Pair( ast.Literal("ppid"), ast.Resolve( ast.Resolve(ast.Var("proc"), ast.Literal("parent")), ast.Literal("pid"))), ast.Pair(ast.Literal("pid"), ast.Resolve(ast.Var("proc"), ast.Literal("pid"))), ast.Pair(ast.Literal("column_2"), ast.Literal("foo")), ast.Pair( ast.Literal("asdate"), ast.Apply( ast.Var("asdate"), ast.Resolve(ast.Var("proc"), ast.Literal("starttime")))), ast.Pair( ast.Literal("fd_5"), ast.Select( ast.Resolve(ast.Var("proc"), ast.Literal("fd")), ast.Literal(5))))))
def select_what(self): # Each value we select is in form EXPRESSION [AS SYMBOL]. Values are # separated by commas. start = self.tokens.matched.start used_names = set() # Keeps track of named values to prevent duplicates. vars = [] for idx in itertools.count(): value_expression = self.expression() if self.tokens.accept(grammar.select_as): # If there's an AS then we have an explicit name for this value. self.tokens.expect(common_grammar.symbol) if self.tokens.matched.value in used_names: return self.error( "Duplicate 'AS' name %r." % self.tokens.matched.value) key_expression = ast.Literal(self.tokens.matched.value, start=self.tokens.matched.start, end=self.tokens.matched.end, source=self.original) # Record the value expression of the alias. self.aliases[-1][self.tokens.matched.value] = value_expression used_names.add(self.tokens.matched.value) else: # Try to guess the appropriate name of the column based on what # the expression is. name = self._guess_name_of(value_expression) if (not name or name in used_names or (self.scope and name in self.scope)): # Give up and just use the current idx for key. name = "column_%d" % (idx,) else: used_names.add(name) key_expression = ast.Literal(name) end = key_expression.end or value_expression.end vars.append(ast.Pair(key_expression, value_expression, start=value_expression.start, end=end, source=self.original)) if self.tokens.accept(grammar.select_from): # Make ast.Bind here. source_expression = self.select_from() return ast.Map( source_expression, ast.Bind(*vars, start=start, end=vars[-1].end, source=self.original), start=start, end=self.tokens.matched.end, source=self.original) self.tokens.expect(common_grammar.comma)
def testLet(self): self.assertQueryMatches( "let x = 5, y = 10 x + y", ast.Let( ast.Bind(ast.Pair(ast.Literal("x"), ast.Literal(5)), ast.Pair(ast.Literal("y"), ast.Literal(10))), ast.Sum(ast.Var("x"), ast.Var("y")))) self.assertQueryMatches( "let( (x = 5 - 3,y=(10+(10)) ) )x + y", ast.Let( ast.Bind( ast.Pair(ast.Literal("x"), ast.Difference(ast.Literal(5), ast.Literal(3))), ast.Pair(ast.Literal("y"), ast.Sum(ast.Literal(10), ast.Literal(10)))), ast.Sum(ast.Var("x"), ast.Var("y")))) self.assertQueryRaises("let x = 5) x + 5") self.assertQueryRaises("let ((x = 5) x + 5") self.assertQueryRaises("let (x = 5)) x + 5") self.assertQueryRaises("let (x = 5 x + 5") self.assertQueryRaises("let (x = 5)")
def testFullSelect(self): query = ("SELECT proc.parent.pid AS ppid_column, proc.pid" " FROM pslist(pid: 10, ppid: 20)" " WHERE count(proc.open_files) > 10" " ORDER BY proc.command DESC" " LIMIT 10 - 9 OFFSET add(5, 10)") expected = ast.Map( ast.Apply( ast.Var("take"), ast.Difference(ast.Literal(10), ast.Literal(9)), ast.Apply( ast.Var("drop"), ast.Apply(ast.Var("add"), ast.Literal(5), ast.Literal(10)), ast.Apply( ast.Var("reverse"), ast.Sort( ast.Filter( ast.Apply( ast.Var("pslist"), ast.Pair(ast.Var("pid"), ast.Literal(10)), ast.Pair(ast.Var("ppid"), ast.Literal(20))), ast.StrictOrderedSet( ast.Literal(10), ast.Apply( ast.Var("count"), ast.Resolve( ast.Var("proc"), ast.Literal("open_files"))), )), ast.Resolve(ast.Var("proc"), ast.Literal("command")))))), ast.Bind( ast.Pair( ast.Literal("ppid_column"), ast.Resolve( ast.Resolve(ast.Var("proc"), ast.Literal("parent")), ast.Literal("pid"))), ast.Pair(ast.Literal("pid"), ast.Resolve(ast.Var("proc"), ast.Literal("pid"))))) self.assertQueryMatches(query, expected)
def testBuiltins(self): self.assertQueryMatches( "filter(pslist(), proc.pid == 1)", ast.Filter( ast.Apply(ast.Var("pslist")), ast.Equivalence( ast.Resolve(ast.Var("proc"), ast.Literal("pid")), ast.Literal(1)))) self.assertQueryMatches( "map(pslist(), [proc.pid, proc['command']])", ast.Map( ast.Apply(ast.Var("pslist")), ast.Tuple(ast.Resolve(ast.Var("proc"), ast.Literal("pid")), ast.Select(ast.Var("proc"), ast.Literal("command"))))) self.assertQueryMatches( "bind(x: 1, y: 2)", ast.Bind(ast.Pair(ast.Var("x"), ast.Literal(1)), ast.Pair(ast.Var("y"), ast.Literal(2)))) self.assertQueryRaises("bind (x: 1, y: 2)")