예제 #1
0
def serialize_project(node, context):
    return IR.select(
        node.kind_name,
        filters=IR.filter(
            IR.attribute(None, "name"), IR.literal(node.name), "="
        ),
        limit=1,
    )
예제 #2
0
def compile_constant(node, state):
    expr = IR.literal(node.value)

    # Constants are represented as repr(obj) in the
    # serialization part, so we have to re-cast it.
    if state.match == "Constant":
        expr.value = repr(expr.value)

    return IR.filter(state.compute_path(), expr, "=")
예제 #3
0
def compile_sequence(node, state):
    total_length = len(node.items)
    verify_call = IR.call("count", [state.compute_path()])

    length_verifier = IR.filter(verify_call, total_length, "=")

    if total := node.items.count(grammar.Expand):
        state.ensure(node, total == 1)
        length_verifier = IR.filter(verify_call, total_length - 1, ">=")
예제 #4
0
def apply_ast(node, context):
    with context.enter_node(node):
        insertions = {
            field: serialize(value, context)
            for field, value in iter_properties(node)
            if value is not None
        }

    query = IR.insert(node.kind_name, insertions)
    return context.connection.query_one(IR.construct(query))
예제 #5
0
def serialize_ast(node, context):
    if node.is_enum:
        # <ast::op>'Add'
        return IR.enum_member(node.base_name, node.kind_name)
    else:
        # (INSERT ast::BinOp {.left := ..., ...})
        reference = apply_ast(node, context)
        context.new_reference(reference.id)

        # (SELECT ast::expr FILTER .id = ... LIMIT 1)
        return IR.select(
            node.base_name, filters=IR.object_ref(reference), limit=1
        )
예제 #6
0
def metadata_parent(parent_node, state):
    state.ensure(parent_node, len(parent_node.filters) == 1)

    parent_field, filter_value = parent_node.filters.popitem()
    state.ensure(parent_node, filter_value is grammar.Ignore)

    with state.temp_pointer("_parent_types"):
        return IR.filter(
            IR.tuple(
                [parent_node.bound_node.type_id,
                 IR.literal(parent_field)]),
            state.compute_path(),
            "IN",
        )
예제 #7
0
def compile_reference(node, state):
    obtained_type = state.field_info.type

    if pointer := state.scope.lookup(node.name):
        expected_type = pointer.field_info.type
        state.ensure(node, expected_type is obtained_type)

        left = state.compute_path()
        right = pointer.compute_path()

        if issubclass(expected_type, ast.expr):
            left = IR.attribute(left, "_tag")
            right = IR.attribute(right, "_tag")

        return IR.filter(left, right, "=")
예제 #8
0
def convert_meta(node, state, arguments):
    state.ensure(node, state.pointer == "__metadata__")

    filters = None
    if arguments.parent:
        filters = IR.combine_filters(filters,
                                     metadata_parent(arguments.parent, state))
    return filters
예제 #9
0
def aggregate_array(state):
    # If we are in a nested list search (e.g: Call(args=[Call(args=[Name()])]))
    # we can't directly use `ORDER BY @index` since the EdgeDB can't quite infer
    # which @index are we talking about.
    if len(state.parents) >= 1:
        path = IR.attribute(
            IR.typed(IR.name(_COMPILER_WORKAROUND_FOR_TARGET), state.match),
            state.pointer,
        )
        body = IR.loop(
            IR.name(_COMPILER_WORKAROUND_FOR_TARGET),
            state.parents[-1].compute_path(allow_missing=True),
            IR.select(path, order=IR.property("index")),
        )
    else:
        body = IR.select(state.compute_path(), order=IR.property("index"))

    return IR.call("array_agg", [body])
예제 #10
0
    def compute_path(self, allow_missing=False):
        parent, *parents = self.get_ordered_parents()

        def get_pointer(state, allow_missing):
            pointer = state.pointer
            if allow_missing:
                pointer = IR.optional(pointer)
            return pointer

        base = get_pointer(parent, allow_missing)
        if not parent.is_flag_set("in for loop"):
            base = IR.attribute(None, base)

        for parent in parents:
            base = IR.typed(base, parent.match)
            base = IR.attribute(base, get_pointer(parent, allow_missing))

        return base
예제 #11
0
def run_query_on_connection(
    connection,
    reiz_ql,
    *,
    limit=DEFAULT_LIMIT,
    offset=0,
):
    query = IR.construct(compile_query(reiz_ql, limit, offset))
    query_set = connection.query(query)
    return process_queryset(query_set)
예제 #12
0
def compile_matcher(node, state):
    if state is None:
        state = CompilerState(node.name)
    else:
        state = CompilerState.from_parent(node.name, state)

    filters = None
    for key, value in node.filters.items():
        if value is grammar.Ignore:
            continue

        if right_filter := state.compile(key, value):
            filters = IR.combine_filters(filters, right_filter)
예제 #13
0
async def run_query_on_async_connection(
    connection,
    reiz_ql,
    *,
    limit=DEFAULT_LIMIT,
    offset=0,
    loop=None,
    timeout=config.web.timeout,
):
    query = IR.construct(compile_query(reiz_ql, limit, offset))
    query_set = await asyncio.wait_for(connection.query(query),
                                       timeout=timeout,
                                       loop=loop)
    return process_queryset(query_set)
예제 #14
0
 def compile_query(self):
     query = compile_query(self.reiz_ql, limit=None, offset=0)
     query.filters = IR.combine_filters(
         query.filters,
         IR.filter(
             IR.attribute(IR.attribute(None, "_module"), "filename"),
             IR.literal(self.expected_filename),
             "=",
         ),
     )
     return IR.construct(query)
예제 #15
0
async def analyze_query(request):
    if "query" not in request.json:
        return error("Missing 'query' data")

    results = dict.fromkeys(("exception", "reiz_ql", "edge_ql"))
    try:
        reiz_ql = parse_query(request.json["query"])
        results["reiz_ql"] = normalize(asdict(reiz_ql))
        results["edge_ql"] = IR.construct(compile_to_ir(reiz_ql))
    except ReizQLSyntaxError as syntax_err:
        results["status"] = "error"
        results["exception"] = syntax_err.message
        results.update(syntax_err.position)
    else:
        results["status"] = "success"

    return json_response(results)
예제 #16
0
def main():
    parser = ArgumentParser()
    parser.add_argument(
        "source",
        type=FileType(mode="rb"),
        nargs="?",
        default="-",
        help="the file to parse; defaults to stdin",
    )
    parser.add_argument(
        "--do-not-optimize",
        action="store_false",
        help="do not generated optimized IR",
    )
    options = parser.parse_args()
    with options.source:
        query = parse_query(options.source.read())
        pprint(query)

        ir = compile_to_ir(query)
        print(
            IR.construct(ir, optimize=options.do_not_optimize, top_level=True))
예제 #17
0
def convert_length(node, state, arguments):
    state.ensure(node, any((arguments.min, arguments.max)))

    count = IR.call("count", [state.compute_path()])
    filters = None
    for value, operator in [
        (arguments.min, IR.as_operator(">=")),
        (arguments.max, IR.as_operator("<=")),
    ]:
        if value is None:
            continue

        state.ensure(value, isinstance(value, grammar.Constant))
        state.ensure(value, isinstance(value.value, int))
        filters = IR.combine_filters(
            filters, IR.filter(count, IR.literal(value.value), operator))

    assert filters is not None
    return filters
예제 #18
0
def convert_match_enum(node, state):
    expr = IR.enum_member(node.base, node.name)
    return IR.filter(state.compute_path(), expr, "=")
예제 #19
0
def convert_all_any(node, state, arguments):
    return IR.call(node.name.lower(), [state.codegen(arguments.value)])
예제 #20
0
def serialize_string(value, context):
    return IR.literal(value)
예제 #21
0
def serialize_tuple(sequence, context):
    return IR.tuple([serialize(value, context) for value in sequence])
예제 #22
0
def serialize_sequence(sequence, context):
    ir_set = IR.set([serialize(value, context) for value in sequence])

    if all(isinstance(item, _BASIC_SET_TYPES) for item in sequence):
        # {1, 2, 3} / {<ast::op>'Add', <ast::op>'Sub', ...}
        return ir_set
    else:
        # Inserting a sequence of AST objects would require special
        # attention to calculate the index property.
        target = IR.name("item")
        scope = IR.namespace({"items": ir_set})
        loop = IR.loop(
            target,
            IR.call("enumerate", [IR.name("items")]),
            IR.select(
                IR.attribute(target, 1),
                selections=[
                    IR.assign(IR.property("index"), IR.attribute(target, 0))
                ],
            ),
        )
        return IR.add_namespace(scope, loop)
예제 #23
0
    def sync(self, connection):
        query_set = connection.query(IR.construct_prepared("module.filenames"))
        self.files = {module.filename for module in query_set}

        query_set = connection.query(IR.construct_prepared("project.names"))
        self.projects = {project.name for project in query_set}
예제 #24
0
    if state is None:
        state = CompilerState(node.name)
    else:
        state = CompilerState.from_parent(node.name, state)

    filters = None
    for key, value in node.filters.items():
        if value is grammar.Ignore:
            continue

        if right_filter := state.compile(key, value):
            filters = IR.combine_filters(filters, right_filter)

    if state.is_root:
        state.scope.exit()
        if state_filters := IR.unpack_filters(state.filters):
            filters = IR.combine_filters(filters, state_filters)
        if state.variables:
            namespace = IR.namespace(state.variables)
            filters = IR.add_namespace(namespace, IR.select(filters))
        return IR.select(state.match, filters=filters)

    if filters is None:
        filters = IR.filter(state.parents[-1].compute_path(),
                            IR.wrap(state.match), "IS")

    return filters


@codegen.register(grammar.MatchEnum)
def convert_match_enum(node, state):
예제 #25
0
from reiz.serialization.statistics import Insertion, Statistics
from reiz.utilities import _available_cores, guarded, logger


@guarded(Insertion.FAILED, ignored_exceptions=(InternalDatabaseError, ))
def insert_file(context):
    if context.is_cached():
        return Insertion.CACHED

    if not (tree := context.as_ast()):
        return Insertion.SKIPPED

    with context.connection.transaction():
        module = apply_ast(tree, context)
        module_select = IR.select(tree.kind_name,
                                  filters=IR.object_ref(module),
                                  limit=1)

        update_filter = IR.filter(
            IR.attribute(None, "id"),
            IR.call("array_unpack",
                    [IR.cast("array<uuid>", IR.variable("ids"))]),
            "IN",
        )
        for base_type in Schema.module_annotated_types:
            update = IR.update(
                base_type.kind_name,
                filters=update_filter,
                assignments={"_module": module_select},
            )
            context.connection.query(IR.construct(update),
예제 #26
0
def convert_logical_operator(node, state):
    if node is grammar.LogicOperator.OR:
        return IR.as_operator("OR")
    elif node is grammar.LogicOperator.AND:
        return IR.as_operator("AND")
예제 #27
0
def convert_logical_operation(node, state):
    return IR.filter(
        state.codegen(node.left),
        state.codegen(node.right),
        state.codegen(node.operator),
    )
예제 #28
0
def compile_operator_flip(node, state):
    return IR.negate(state.codegen(node.value))
예제 #29
0
def compile_match_string(node, state):
    expr = IR.literal(node.value)
    return IR.filter(state.compute_path(), expr, "LIKE")
예제 #30
0
def convert_none(node, state):
    return IR.negate(IR.exists(state.compute_path()))