예제 #1
0
    def test_from_ast(self):
        expected = [
            AST(
                'filter',
                AST(
                    'cond_eq', [
                        AST('prop', 'foo'),
                        AST('val', 'bar')
                    ]
                )
            )
        ]

        attrs = {
            'find_elements.return_value': []
        }
        self.feature.configure_mock(**attrs)

        q = self.query.from_ast(expected)

        self.assertIsInstance(q, Query)
        self.assertEqual(q.ast, expected)

        list(q)

        self.feature.find_elements.assert_called_with(expected)
예제 #2
0
    def get_ast(self):
        ast = AST(
            'join_{0}'.format(self.name),
            [self.left.get_ast(), self.right.get_ast()])

        if self.inverted:
            return AST('not', ast)

        else:
            return ast
예제 #3
0
파일: driver.py 프로젝트: linkdd/link.mongo
    def process_query(self, query):
        if query['type'] == Driver.QUERY_CREATE:
            ast = AST('insert', query['update'])
            doc = self.wupdate.walk(self.mbuilder.parse(ast), {})

            return self.obj.insert(doc)

        elif query['type'] in [Driver.QUERY_READ, Driver.QUERY_COUNT]:
            ast = query['filter']
            mfilter, s = {}, slice(None)
            aggregation = False

            if ast:
                ast = AST('query', ast)
                result = self.wfilter.walk(self.mbuilder.parse(ast))

                if isinstance(result, tuple):
                    mfilter, s = result

                else:
                    aggregation = True

            if not aggregation:
                result = self.obj.find(mfilter, skip=s.start, limit=s.stop)

            else:
                result = self.obj.aggregate(result)

            if query['type'] == Driver.QUERY_COUNT:
                result = result.count()

            return result

        elif query['type'] == Driver.QUERY_UPDATE:
            filter_ast = AST('query', query['filter'])
            update_ast = AST('update', query['update'])

            mfilter, _ = self.wfilter.walk(self.mbuilder.parse(filter_ast))
            uspec = self.wupdate.walk(self.mbuilder.parse(update_ast), {})

            result = self.obj.update(mfilter, uspec, multi=True)

            return result.modified_count

        elif query['type'] == Driver.QUERY_DELETE:
            ast = AST('query', query['filter'])
            mfilter, _ = self.wfilter.walk(self.mbuilder.parse(ast))

            result = self.obj.delete(mfilter, multi=True)

            return result.deleted_count
예제 #4
0
    def update(self, *fields):
        """
        Update elements matching the query.

        :param fields: Assignments
        :type fields: list of A

        :returns: Number of modified elements.
        :rtype: int
        """

        c = self._copy()

        fields_ast = []

        for field in fields:
            if not isinstance(field, A):
                raise TypeError('Supplied field is not supported: {0}'.format(
                    type(field)))

            fields_ast.append(field.get_ast())

        c.ast.append(AST('update', fields_ast))

        return self.manager.execute(c.ast)
예제 #5
0
    def delete(self):
        """
        Delete element from store.
        """

        condition = self._get_filter()

        self.driver.remove_elements([AST('filter', condition.get_ast())])
예제 #6
0
    def get_ast(self):
        """
        Returns simplified AST.

        :returns: AST node as dict
        :rtype: dict
        """

        return AST('node', self.name)
예제 #7
0
    def group(self, key, *expressions):
        """
        Group elements by key matching the query using the expressions.

        :param key: Key used to group elements
        :type key: str

        :param expressions: Expressions
        :type expressions: list of CombinableExpression

        :returns: Grouped elements.
        """

        c = self._copy()
        c.ast.append(
            AST('group', [AST('prop', key)] +
                [expression.get_ast() for expression in expressions]))

        return self.manager.execute(c.ast)
예제 #8
0
    def delete(self):
        """
        Delete elements matching the query.

        :returns: Number of deleted elements.
        :rtype: int
        """

        c = self._copy()
        c.ast.append(AST('delete', None))

        return self.manager.execute(c.ast)
예제 #9
0
    def count(self):
        """
        Count elements matched by this query.

        :returns: Number of matching elements
        :rtype: int
        """

        c = self._copy()
        c.ast.append(AST('count', None))

        return self.manager.execute(c.ast)
예제 #10
0
    def get(self, condition):
        """
        Get a single element matching the filter.

        :param condition: Filter
        :type condition: C or CombinedCondition

        :returns: Matching element or None
        :rtype: Model or None
        """

        if not isinstance(condition, (C, CombinedCondition)):
            raise TypeError('Supplied condition is not supported: {0}'.format(
                type(condition)))

        return self.execute(AST('get', condition.get_ast()))
예제 #11
0
    def __getitem__(self, s):
        """
        Returns a new query with a slice of filtered elements.

        :param s: query's slice
        :type s: slice

        :returns: Query
        :rtype: Query
        """

        c = self._copy()

        if not isinstance(s, slice):
            s = slice(s)

        c.ast.append(AST('slice', s))

        return c
예제 #12
0
    def get(self, condition):
        """
        Add filter to the query, and get a single element matching the query.

        :param condition: Filter
        :type condition: C or CombinedCondition

        :returns: Matching element or None
        :rtype: Model or None
        """

        c = self._copy()

        if not isinstance(condition, (C, CombinedCondition)):
            raise TypeError('Supplied condition is not supported: {0}'.format(
                type(condition)))

        c.ast.append(AST('get', condition.get_ast()))

        return self.manager.execute(c.ast)
예제 #13
0
    def exclude(self, condition):
        """
        Returns a new query with a new (negated) filter added.

        :param condition: Filter
        :type condition: C or CombinedCondition

        :returns: Query
        :rtype: Query
        """

        c = self._copy()

        if not isinstance(condition, (C, CombinedCondition)):
            raise TypeError('Supplied condition is not supported: {0}'.format(
                type(condition)))

        c.ast.append(AST('exclude', condition.get_ast()))

        return c
예제 #14
0
    def create(self, *fields):
        """
        Put a new element into the store.

        :param fields: List of assignments
        :type fields: list of A

        :returns: Created element
        :rtype: Model
        """

        fields_ast = []

        for field in fields:
            if not isinstance(field, A):
                raise TypeError('Supplied field is not supported: {0}'.format(
                    type(field)))

            fields_ast.append(field.get_ast())

        return self.execute(AST('create', fields_ast))
예제 #15
0
    def test_validate_ast(self):
        with self.assertRaises(ASTSingleStatementError):
            self.query.validate_ast(AST('not_get_or_create', 'unused'))

        for stmt in ['update', 'delete', 'get', 'count', 'group']:
            with self.assertRaises(ASTLastStatementError):
                self.query.validate_ast([
                    AST(stmt, 'unused'),
                    AST('unused', 'unused')
                ])

        with self.assertRaises(ASTInvalidStatementError):
            self.query.validate_ast([
                AST('unknown', 'unused')
            ])

        with self.assertRaises(ASTInvalidFormatError):
            self.query.validate_ast('invalid format')

        self.query.validate_ast([
            AST('filter', 'unused'),
            AST('update', 'unused')
        ])
예제 #16
0
 def get_ast(self):
     return AST('cond_{0}'.format(self.operator),
                [AST('prop', self.name),
                 self.value.get_ast()])
예제 #17
0
 def get_ast(self):
     return AST(
         'op_{0}'.format(self.name),
         [self.left.get_ast(), self.right.get_ast()])
예제 #18
0
 def get_ast(self):
     return AST('ref', self.name)
예제 #19
0
 def get_ast(self):
     return AST('func_{0}'.format(self.name),
                [arg.get_ast() for arg in self.arguments])
예제 #20
0
 def get_ast(self):
     return AST('val', self.name)
예제 #21
0
 def get_ast(self):
     return AST('assign', [
         AST('prop', self.name),
         self.value.get_ast() if self.value else AST('val', None)
     ])