Esempio n. 1
0
def make_delete_rv(t):
    noop = "noop" in t.parser.request.args

    # a new delete inner statement enforces that we only delete
    # things which we have the key for.
    if len(t) > 2 and t[2] == 'where':
        # delete the whole stream, gone.  this also deletes the
        # data in the backend readingdb.
        if not noop:
            statement = "DELETE FROM stream"
            returning = "RETURNING id, uuid"
        else:
            statement = "SELECT uuid FROM stream"
            returning = ""
        return ext_deletor if not noop else ext_default, \
            """%(statement)s WHERE id IN (
                 SELECT s.id FROM stream s, subscription sub 
                 WHERE (%(restrict)s) AND s.subscription_id = sub.id AND 
                 (%(auth)s)
               ) %(returning)s
            """ % {
            'restrict': t[3].render(),
            'auth': qg.build_authcheck(t.parser.request, forceprivate=True),
            'statement': statement,
            'returning': returning
            }
    else:
        # to make the return value right, we need to tweak the
        # where clause.  we want to only select streams where
        # there's actually something to delete, since all of the
        # streams the where-clause hits will get returned.
        tag_clause = ast.Statement(
            ast.Statement.OP_OR,
            *[ast.Statement(ast.Statement.OP_HAS, tag) for tag in t[2]])
        if len(t) > 3:
            where_clause = ast.Statement(ast.Statement.OP_AND, tag_clause,
                                         t[4])
        else:
            # if there's no where clause, we only look at streams
            # with the right tag.
            where_clause = tag_clause
        # this alters the tags but doesn't touch the data
        del_tags = ', '.join(map(escape_string, t[2]))
        if not noop:
            statement = "UPDATE stream SET metadata = metadata - ARRAY[" + \
                del_tags + "]"
            returning = "RETURNING id, uuid"
        else:
            statement = "SELECT id, uuid FROM stream"
            returning = ""

        q = statement + " WHERE id IN " + \
            "(SELECT s.id FROM stream s, subscription sub " + \
            "WHERE (" + where_clause.render() + ") AND s.subscription_id = sub.id AND " + \
            qg.build_authcheck(t.parser.request, forceprivate=True)  + ")" + returning
        return ext_tag_deletor, q
Esempio n. 2
0
def p_statement_unary(t):
    """statement_unary : HAS LVALUE
                       | CONTAINS QSTRING
    """
    if t[1] == 'has':
        if t[2] == 'uuid':
            t[0] = ast.Statement(ast.Statement.OP_UUID)
        else:
            t[0] = ast.Statement(ast.Statement.OP_HAS, t[2])
    elif t[1] == 'contains':
        t[0] = ast.Statement(ast.Statement.OP_CONTAINS, t[2])
Esempio n. 3
0
def p_statement_binary(t):
    """statement_binary : LVALUE '=' QSTRING
                        | LVALUE LIKE QSTRING
                        | LVALUE TILDE QSTRING
    """
    if t[1] == 'uuid':
        t[0] = ast.Statement(ast.Statement.OP_UUID, t[2], t[3])
    else:
        if t[2] == '=':
            t[0] = ast.Statement(ast.Statement.OP_EQUALS, t[1], t[3])
        elif t[2] == 'like':
            t[0] = ast.Statement(ast.Statement.OP_LIKE, t[1], t[3])
        elif t[2] == '~':
            t[0] = ast.Statement(ast.Statement.OP_REGEX, t[1], t[3])
Esempio n. 4
0
def p_statement(t):
    """statement : statement_unary
                 | statement_binary
                 | '(' statement ')'
                 | statement AND statement
                 | statement OR statement
                 | NOT statement
                """
    if len(t) == 2:
        t[0] = t[1]
    elif t[2] == 'and':
        t[0] = ast.Statement(ast.Statement.OP_AND, t[1], t[3])
    elif t[2] == 'or':
        t[0] = ast.Statement(ast.Statement.OP_OR, t[1], t[3])
    elif t[1] == 'not':
        t[0] = ast.Statement(ast.Statement.OP_NOT, t[2])
    else:
        t[0] = t[2]
Esempio n. 5
0
def make_set_rv(t):
    # build the query for a set expression
    if len(t) > 3:
        # if there is a where clause, grab it
        where_clause = t[4]
    else:
        # if no where clause, just do something fast that matches
        # everything
        where_clause = ast.Statement(ast.Statement.OP_UUID)
    noop = "noop" in t.parser.request.args

    # build a list of what tags we're updating, as well as the
    # name of the regex tag.  We're currently not smart enough to
    # deal with more than one regex match in a set statement, due
    # to issues with back references.
    new_tags, regex_tag = build_setstring(t[2], where_clause)
    tag_list = [v[0] for v in t[2]]
    if regex_tag: tag_list.append(regex_tag)

    # if we're in noop mode, we need to tweak the SQL
    if not noop:
        command = "UPDATE stream SET metadata = metadata || "
        from_stmt = ""
    else:
        command = "SELECT uuid, "
        from_stmt = "FROM stream"

    # build the first part of the query that depends on if this is a noop
    q = "%(command)s %(hstore_expression)s %(from_stmt)s WHERE ID IN" % {
        "command": command,
        "hstore_expression": new_tags,
        "from_stmt": from_stmt
    }

    # the where caluse always looks the same
    q += "(SELECT s.id FROM stream s, subscription sub " + \
        "WHERE (" + where_clause.render() + ") AND s.subscription_id = sub.id AND " + \
        qg.build_authcheck(t.parser.request, forceprivate=True)  + ") "

    if not noop:
        # return the list of modifications.  if this was a noop we
        # get this for free.
        q += " RETURNING uuid, slice(metadata, ARRAY[" + \
            ','.join((escape_string(v) for v in tag_list)) + "])"
    return lambda x: ext_set(tag_list, x), q
Esempio n. 6
0
def p_statement_unary(t):
    """statement_unary : HAS LVALUE"""
    if t[1] == 'has':
        t[0] = ast.Statement(ast.Statement.OP_HAS, t[2])