예제 #1
0
def tuple_indirection_set(path_tip: irast.Set, *, source: s_sources.Source,
                          ptr_name: str, source_context: parsing.ParserContext,
                          ctx: context.ContextLevel) -> irast.Set:

    el_name = ptr_name
    el_norm_name = source.normalize_index(ctx.env.schema, el_name)
    el_type = source.get_subtype(ctx.env.schema, el_name)

    path_id = irutils.tuple_indirection_path_id(path_tip.path_id,
                                                el_norm_name,
                                                el_type,
                                                schema=ctx.env.schema)
    expr = irast.TupleIndirection(expr=path_tip,
                                  name=el_norm_name,
                                  path_id=path_id,
                                  context=source_context)

    return generated_set(expr, ctx=ctx)
예제 #2
0
def _is_ptr_or_self_ref(ir_expr: irast.Base, srccls: s_sources.Source,
                        schema: s_schema.Schema) -> bool:
    if not isinstance(ir_expr, irast.Set):
        return False
    else:
        ir_set = ir_expr

        return (isinstance(srccls, s_objtypes.ObjectType)
                and ir_set.expr is None
                and (ir_set.scls == srccls or
                     (ir_set.rptr is not None and srccls.getptr(
                         schema, ir_set.rptr.ptrcls.shortname) is not None)))
예제 #3
0
def resolve_ptr(near_endpoint: s_sources.Source,
                ptr_name: typing.Tuple[str, str],
                direction: s_pointers.PointerDirection,
                target: typing.Optional[s_nodes.Node] = None,
                *,
                source_context: typing.Optional[parsing.ParserContext] = None,
                ctx: context.ContextLevel) -> s_pointers.Pointer:
    ptr_module, ptr_nqname = ptr_name

    if ptr_module:
        pointer = schemactx.get_schema_ptr(name=ptr_nqname,
                                           module=ptr_module,
                                           ctx=ctx)
        pointer_name = pointer.name
    else:
        pointer_name = ptr_nqname

    ptr = None

    if isinstance(near_endpoint, s_sources.Source):
        ptr = near_endpoint.resolve_pointer(ctx.schema,
                                            pointer_name,
                                            direction=direction,
                                            look_in_children=False,
                                            include_inherited=True,
                                            far_endpoint=target)

        if ptr is None:
            if isinstance(near_endpoint, s_links.Link):
                msg = (f'{near_endpoint.displayname} has no property '
                       f'{pointer_name!r}')
                if target:
                    msg += f'of type {target.name!r}'

            elif direction == s_pointers.PointerDirection.Outbound:
                msg = (f'{near_endpoint.displayname} has no link or property '
                       f'{pointer_name!r}')
                if target:
                    msg += f'of type {target.name!r}'

            else:
                path = f'{near_endpoint.name}.{direction}{pointer_name}'
                if target:
                    path += f'[IS {target.name}]'
                msg = f'{path} does not resolve to any known path',

            err = errors.EdgeQLReferenceError(msg, context=source_context)

            if direction == s_pointers.PointerDirection.Outbound:
                s_utils.enrich_schema_lookup_error(
                    err,
                    pointer_name,
                    modaliases=ctx.modaliases,
                    item_types=(s_pointers.Pointer, ),
                    collection=near_endpoint.pointers.values(),
                    schema=ctx.schema)

            raise err

    else:
        if direction == s_pointers.PointerDirection.Outbound:
            bptr = schemactx.get_schema_ptr(pointer_name, ctx=ctx)
            schema_cls = ctx.schema.get('schema::ScalarType')
            if bptr.shortname == 'std::__type__':
                ptr = bptr.derive(ctx.schema, near_endpoint, schema_cls)

    if ptr is None:
        # Reference to a property on non-object
        msg = 'invalid property reference on a primitive type expression'
        raise errors.EdgeQLReferenceError(msg, context=source_context)

    return ptr