Esempio n. 1
0
    def _cmd_tree_from_ast(cls, astnode, context, schema):
        cmd = super()._cmd_tree_from_ast(astnode, context, schema)

        if isinstance(astnode, qlast.CreateConcreteConstraint):
            if astnode.args:
                args = []

                for arg in astnode.args:
                    arg_expr = s_expr.ExpressionText(
                        edgeql.generate_source(arg.arg, pretty=False))
                    args.append(arg_expr)

                cmd.add(sd.AlterObjectProperty(property='args',
                                               new_value=args))

        elif isinstance(astnode, qlast.CreateConstraint):
            if astnode.args:
                paramnames, paramdefaults, paramtypes, paramkinds, variadic = \
                    s_func.parameters_from_ast(
                        astnode, context.modaliases, schema)

                if variadic is not None:
                    cmd.add(
                        sd.AlterObjectProperty(property='varparam',
                                               new_value=variadic))

                for pname, pdefault, ptype in zip(paramnames, paramdefaults,
                                                  paramtypes):
                    if pname is not None:
                        raise ql_errors.EdgeQLError(
                            'constraints do not support named parameters',
                            context=astnode.context)

                    if pdefault is not None:
                        raise ql_errors.EdgeQLError(
                            'constraints do not support parameters '
                            'with defaults',
                            context=astnode.context)

                    if ptype is None:
                        raise ql_errors.EdgeQLError('untyped parameter',
                                                    context=astnode.context)

                cmd.add(
                    sd.AlterObjectProperty(property='paramtypes',
                                           new_value=paramtypes))

        # 'subject' can be present in either astnode type
        if astnode.subject:
            subjectexpr = s_expr.ExpressionText(
                edgeql.generate_source(astnode.subject, pretty=False))

            cmd.add(
                sd.AlterObjectProperty(property='subjectexpr',
                                       new_value=subjectexpr))

        cls._validate_subcommands(astnode)

        return cmd
Esempio n. 2
0
def translate(schema,
              graphql,
              *,
              variables=None,
              operation_name=None,
              modules=None):
    if variables is None:
        variables = {}

    if modules is None:
        modules = set(modules) | {'default'}

    # HACK
    query = re.sub(r'@edgedb\(.*?\)', '', graphql)
    schema2 = gt.GQLCoreSchema(schema, *modules)._gql_schema

    parser = gqlparser.GraphQLParser()
    gqltree = parser.parse(graphql)
    context = GraphQLTranslatorContext(schema=schema,
                                       gqlcore=schema2,
                                       query=query,
                                       variables=variables,
                                       operation_name=operation_name,
                                       modules=modules)
    edge_forest_map = GraphQLTranslator(context=context).visit(gqltree)
    code = []
    for name, (tree, critvars) in sorted(edge_forest_map.items()):
        if name:
            code.append(f'# {name}')
        if critvars:
            crit = [f'{vname}={val!r}' for vname, val in critvars]
            code.append(f'# critical variables: {", ".join(crit)}')
        code += [edgeql.generate_source(tree), ';']

    return '\n'.join(code)
Esempio n. 3
0
    def normalize_constraint_expr(cls,
                                  schema,
                                  module_aliases,
                                  expr,
                                  *,
                                  subject=None,
                                  constraint,
                                  expr_context=None,
                                  enforce_boolean=False):
        from edgedb.lang.ir import utils as irutils

        if subject is None:
            subject = cls._dummy_subject()

        edgeql_tree, ir_result = cls._normalize_constraint_expr(
            schema, module_aliases, expr, subject)

        if enforce_boolean:
            bool_t = schema.get('std::bool')
            expr_type = irutils.infer_type(ir_result, schema)
            if not expr_type.issubclass(bool_t):
                raise s_errors.SchemaDefinitionError(
                    f'{constraint.displayname} constraint expression expected '
                    f'to return a bool value, got {expr_type.name.name!r}',
                    context=expr_context)

        expr = edgeql.generate_source(edgeql_tree, pretty=False)
        # XXX: check that expr has boolean result
        return expr
Esempio n. 4
0
    def _parse_default(cls, cmd):
        return
        for sub in cmd(sd.AlterObjectProperty):
            if sub.property == 'default':
                if isinstance(sub.new_value, sexpr.ExpressionText):
                    expr = edgeql.parse(sub.new_value)

                    if expr.op == qlast.UNION:
                        candidates = []
                        cls._extract_union_operands(expr, candidates)
                        deflt = []

                        for candidate in candidates:
                            cexpr = candidate.result
                            if isinstance(cexpr, qlast.Constant):
                                deflt.append(cexpr.value)
                            else:
                                text = edgeql.generate_source(candidate,
                                                              pretty=False)
                                deflt.append(sexpr.ExpressionText(text))
                    else:
                        deflt = [sub.new_value]

                else:
                    deflt = [sub.new_value]

                sub.new_value = deflt
Esempio n. 5
0
def translate(schema, graphql, *, variables=None, operation_name=None,
              modules=None):
    if variables is None:
        variables = {}

    if modules is None:
        modules = set(modules) | {'default'}

    # HACK
    query = re.sub(r'@edgedb\(.*?\)', '', graphql)
    schema2 = gt.GQLCoreSchema(schema, *modules)._gql_schema

    parser = gqlparser.GraphQLParser()
    gqltree = parser.parse(graphql)
    context = GraphQLTranslatorContext(
        schema=schema, gqlcore=schema2, query=query,
        variables=variables, operation_name=operation_name, modules=modules)
    edge_forest_map = GraphQLTranslator(context=context).visit(gqltree)
    code = []
    for name, (tree, critvars) in sorted(edge_forest_map.items()):
        if name:
            code.append(f'# {name}')
        if critvars:
            crit = [f'{vname}={val!r}' for vname, val in critvars]
            code.append(f'# critical variables: {", ".join(crit)}')
        code += [edgeql.generate_source(tree), ';']

    return '\n'.join(code)
Esempio n. 6
0
    def _encode_default(self, context, node, op):
        if op.new_value:
            expr = op.new_value
            if not isinstance(expr, sexpr.ExpressionText):
                expr_t = qlast.SelectQuery(
                    result=qlast.Constant(value=expr)
                )
                expr = edgeql.generate_source(expr_t, pretty=False)

                op.new_value = sexpr.ExpressionText(expr)
            super()._apply_field_ast(context, node, op)
Esempio n. 7
0
File: ddl.py Progetto: virajs/edgedb
def ddl_text_from_delta_command(delta):
    """Return DDL text for a delta command tree."""
    if isinstance(delta, s_db.AlterDatabase):
        commands = delta
    else:
        commands = [delta]

    text = []
    for command in commands:
        delta_ast = ddl_from_delta(command)
        if delta_ast:
            stmt_text = edgeql.generate_source(edgeql.optimize(
                delta_ast, strip_builtins=False))
            text.append(stmt_text + ';')

    return '\n'.join(text)
Esempio n. 8
0
    def _cmd_tree_from_ast(cls, astnode, context, schema):
        cmd = super()._cmd_tree_from_ast(astnode, context, schema)

        parent_ctx = context.get(sd.CommandContextToken)
        subject_name = parent_ctx.op.classname

        cmd.update((
            sd.AlterObjectProperty(
                property='subject',
                new_value=so.ObjectRef(classname=subject_name)
            ),
            sd.AlterObjectProperty(
                property='expr',
                new_value=expr.ExpressionText(
                    edgeql.generate_source(astnode.expr, pretty=False))
            )
        ))

        return cmd
Esempio n. 9
0
    def process_specialized_constraint(cls, schema, constraint, params=None):
        from edgedb.lang.edgeql import utils as edgeql_utils
        from edgedb.lang.edgeql import parser as edgeql_parser

        assert constraint.subject is not None

        module_aliases = {}

        # check to make sure that the specialized constraint doesn't redefine
        # an already defined subjectexpr
        if constraint.subjectexpr is not None:
            for base in constraint.bases:
                base_se = base.get_field_value('subjectexpr')
                if base_se and base_se != constraint.subjectexpr:
                    raise s_errors.InvalidConstraintDefinitionError(
                        'subjectexpr is already defined for ' +
                        f'{constraint.name!r}')

        subject = constraint.subject
        subjectexpr = constraint.get_field_value('subjectexpr')
        if subjectexpr:
            _, subject = cls._normalize_constraint_expr(
                schema, {}, subjectexpr, subject)

        expr = constraint.get_field_value('expr')
        if not expr:
            raise s_errors.InvalidConstraintDefinitionError(
                f'missing constraint expression in {constraint.name!r}')

        expr_ql = edgeql_parser.parse(expr, module_aliases)

        if params:
            args = params
        else:
            args = constraint.get_field_value('args')

        args_map = None
        if args:
            if constraint.varparam is not None:
                varparam = constraint.varparam
            else:
                varparam = None

            args_ql = [
                edgeql_parser.parse(arg, module_aliases) for arg in args
            ]

            args_map = edgeql_utils.index_parameters(args_ql,
                                                     varparam=varparam)

            edgeql_utils.inline_parameters(expr_ql, args_map)

            args_map = {
                f'${name}': edgeql.generate_source(val, pretty=False)
                for name, val in args_map.items()
            }

            constraint.errmessage = constraint.errmessage.format(
                __subject__='{__subject__}', **args_map)

            args = list(args_map.values())

        if expr == '__subject__':
            expr_context = \
                constraint.get_attribute_source_context('subjectexpr')
        else:
            expr_context = \
                constraint.get_attribute_source_context('expr')

        expr_text = cls.normalize_constraint_expr(schema,
                                                  module_aliases,
                                                  expr_ql,
                                                  subject=subject,
                                                  constraint=constraint,
                                                  enforce_boolean=True,
                                                  expr_context=expr_context)

        constraint.expr = expr_text
        constraint.localfinalexpr = expr_text
        constraint.finalexpr = expr_text

        constraint.args = args or None
Esempio n. 10
0
    def _cmd_tree_from_ast(cls, astnode, context, schema):
        propname = astnode.name.name
        if astnode.name.module:
            propname = astnode.name.module + '::' + propname

        assert '::' not in propname

        if isinstance(astnode, qlast.DropAttributeValue):
            parent_ctx = context.get(CommandContextToken)
            parent_cls = parent_ctx.op.get_schema_metaclass()

            field = parent_cls._fields.get(propname)
            if (field is not None and issubclass(
                    field.type[0], typed.AbstractTypedCollection)):
                value = field.type[0]()
            else:
                value = None

            return cls(property=propname, new_value=value)

        if astnode.as_expr:
            new_value = s_expr.ExpressionText(
                edgeql.generate_source(astnode.value, pretty=False))
        else:
            if isinstance(astnode.value, qlast.Constant):
                new_value = astnode.value.value
            elif isinstance(astnode.value, qlast.Tuple):
                new_value = tuple(el.value for el in astnode.value.elements)
            elif isinstance(astnode.value, qlast.Mapping):
                m = {}
                for k, v in zip(astnode.value.keys, astnode.value.values):
                    k = k.value
                    if isinstance(v, qlast.Constant):
                        v = v.value
                    elif isinstance(v, qlast.Tuple):
                        v = tuple(el.value for el in v.elements)
                    elif (isinstance(v, qlast.FunctionCall)
                          and v.func == 'typeref'):
                        if len(v.args) > 1:
                            # collection
                            ct = s_types.Collection.get_class(v.args[0].value)
                            subtypes = []
                            for st in v.args[1:]:
                                stname = s_name.Name(v.args[1].value)
                                subtypes.append(so.ObjectRef(classname=stname))

                            v = ct.from_subtypes(subtypes)
                        else:
                            v = so.ObjectRef(
                                classname=s_name.Name(v.args[0].value))
                    elif isinstance(v, qlast.TypeCast):
                        v = v.expr.value
                    elif isinstance(v, qlast.UnaryOp):
                        v = edgeql.generate_source(v)
                        # Remove the space between the operator and the operand
                        v = ''.join(v.split(' ', maxsplit=1))
                    else:
                        raise ValueError(f'unexpected value in attribute '
                                         f'{propname!r}: {v!r}')
                    m[k] = v

                new_value = m
            else:
                raise ValueError(
                    f'unexpected value in attribute: {astnode.value!r}')

        return cls(property=propname, new_value=new_value)
Esempio n. 11
0
    def _cmd_tree_from_ast(cls, astnode, context, schema):
        propname = astnode.name.name
        if astnode.name.module:
            propname = astnode.name.module + '::' + propname

        assert '::' not in propname

        if isinstance(astnode, qlast.DropAttributeValue):
            parent_ctx = context.get(CommandContextToken)
            parent_cls = parent_ctx.op.get_schema_metaclass()

            field = parent_cls._fields.get(propname)
            if (field is not None and
                    issubclass(field.type[0], typed.AbstractTypedCollection)):
                value = field.type[0]()
            else:
                value = None

            return cls(property=propname, new_value=value)

        if astnode.as_expr:
            new_value = s_expr.ExpressionText(
                edgeql.generate_source(astnode.value, pretty=False))
        else:
            if isinstance(astnode.value, qlast.Constant):
                new_value = astnode.value.value
            elif isinstance(astnode.value, qlast.Tuple):
                new_value = tuple(el.value for el in astnode.value.elements)
            elif isinstance(astnode.value, qlast.Mapping):
                m = {}
                for k, v in zip(astnode.value.keys, astnode.value.values):
                    k = k.value
                    if isinstance(v, qlast.Constant):
                        v = v.value
                    elif isinstance(v, qlast.Tuple):
                        v = tuple(el.value for el in v.elements)
                    elif (isinstance(v, qlast.FunctionCall) and
                            v.func == 'typeref'):
                        if len(v.args) > 1:
                            # collection
                            ct = s_types.Collection.get_class(v.args[0].value)
                            subtypes = []
                            for st in v.args[1:]:
                                stname = s_name.Name(v.args[1].value)
                                subtypes.append(so.ObjectRef(
                                    classname=stname))

                            v = ct.from_subtypes(subtypes)
                        else:
                            v = so.ObjectRef(
                                classname=s_name.Name(v.args[0].value))
                    elif isinstance(v, qlast.TypeCast):
                        v = v.expr.value
                    elif isinstance(v, qlast.UnaryOp):
                        v = edgeql.generate_source(v)
                        # Remove the space between the operator and the operand
                        v = ''.join(v.split(' ', maxsplit=1))
                    else:
                        raise ValueError(
                            f'unexpected value in attribute '
                            f'{propname!r}: {v!r}')
                    m[k] = v

                new_value = m
            else:
                raise ValueError(
                    f'unexpected value in attribute: {astnode.value!r}')

        return cls(property=propname, new_value=new_value)