def compile_OperatorCall(expr: irast.OperatorCall, *, ctx: context.CompilerContextLevel) -> pgast.BaseExpr: if (str(expr.func_shortname) == 'std::IF' and expr.args[0].cardinality.is_single() and expr.args[2].cardinality.is_single()): if_expr, condition, else_expr = (a.expr for a in expr.args) return pgast.CaseExpr(args=[ pgast.CaseWhen(expr=dispatch.compile(condition, ctx=ctx), result=dispatch.compile(if_expr, ctx=ctx)) ], defresult=dispatch.compile(else_expr, ctx=ctx)) elif (str(expr.func_shortname) == 'std::??' and expr.args[0].cardinality.is_single() and expr.args[1].cardinality.is_single()): l_expr, r_expr = (a.expr for a in expr.args) return pgast.CoalesceExpr(args=[ dispatch.compile(l_expr, ctx=ctx), dispatch.compile(r_expr, ctx=ctx), ], ) elif expr.typemod is ql_ft.TypeModifier.SetOfType: raise errors.UnsupportedFeatureError( f'set returning operator {expr.func_shortname!r} is not supported ' f'in simple expressions') args = _compile_call_args(expr, ctx=ctx) return compile_operator(expr, args, ctx=ctx)
def compile_OperatorCall(expr: irast.OperatorCall, *, ctx: context.CompilerContextLevel) -> pgast.BaseExpr: if (expr.func_shortname == 'std::IF' and expr.args[0].cardinality.is_single() and expr.args[2].cardinality.is_single()): if_expr, condition, else_expr = (a.expr for a in expr.args) return pgast.CaseExpr(args=[ pgast.CaseWhen(expr=dispatch.compile(condition, ctx=ctx), result=dispatch.compile(if_expr, ctx=ctx)) ], defresult=dispatch.compile(else_expr, ctx=ctx)) if expr.typemod is ql_ft.TypeModifier.SET_OF: raise RuntimeError( f'set returning operator {expr.func_shortname!r} is not supported ' f'in simple expressions') args = [dispatch.compile(a.expr, ctx=ctx) for a in expr.args] return compile_operator(expr, args, ctx=ctx)
def compile_OperatorCall(expr: irast.OperatorCall, *, ctx: context.CompilerContextLevel) -> pgast.BaseExpr: if (expr.func_shortname == 'std::IF' and expr.args[0].cardinality is ql_ft.Cardinality.ONE and expr.args[2].cardinality is ql_ft.Cardinality.ONE): if_expr, condition, else_expr = (a.expr for a in expr.args) return pgast.CaseExpr(args=[ pgast.CaseWhen(expr=dispatch.compile(condition, ctx=ctx), result=dispatch.compile(if_expr, ctx=ctx)) ], defresult=dispatch.compile(else_expr, ctx=ctx)) if expr.typemod is ql_ft.TypeModifier.SET_OF: raise RuntimeError( f'set returning operator {expr.func_shortname!r} is not supported ' f'in simple expressions') args = [dispatch.compile(a.expr, ctx=ctx) for a in expr.args] lexpr = rexpr = None if expr.operator_kind is ql_ft.OperatorKind.INFIX: lexpr, rexpr = args elif expr.operator_kind is ql_ft.OperatorKind.PREFIX: rexpr = args[0] elif expr.operator_kind is ql_ft.OperatorKind.POSTFIX: lexpr = args[0] else: raise RuntimeError(f'unexpected operator kind: {expr.operator_kind!r}') if (expr.func_shortname == 'std::=' and expr.args[0].expr.typeref is not None and irtyputils.is_object(expr.args[0].expr.typeref) and expr.args[1].expr.typeref is not None and irtyputils.is_object(expr.args[1].expr.typeref)): sql_oper = '=' elif expr.sql_operator: sql_oper = expr.sql_operator[0] if len(expr.sql_operator) > 1: # Explicit operand types given in FROM SQL OPERATOR if lexpr is not None: lexpr = pgast.TypeCast( arg=lexpr, type_name=pgast.TypeName(name=(expr.sql_operator[1], ))) if rexpr is not None: rexpr = pgast.TypeCast( arg=rexpr, type_name=pgast.TypeName(name=(expr.sql_operator[2], ))) else: sql_oper = common.get_operator_backend_name(expr.func_shortname, expr.func_module_id)[1] result: pgast.BaseExpr = pgast.Expr( kind=pgast.ExprKind.OP, name=sql_oper, lexpr=lexpr, rexpr=rexpr, ) if expr.force_return_cast: # The underlying operator has a return value type # different from that of the EdgeQL operator declaration, # so we need to make an explicit cast here. result = pgast.TypeCast( arg=result, type_name=pgast.TypeName( name=pg_types.pg_type_from_ir_typeref(expr.typeref))) return result
def _compile_grouping_value( stmt: irast.GroupStmt, used_args: AbstractSet[str], *, ctx: context.CompilerContextLevel) -> pgast.BaseExpr: '''Produce the value for the grouping binding saying what is grouped on''' assert stmt.grouping_binding grouprel = ctx.rel # If there is only one thing grouped on, just output the hardcoded if len(used_args) == 1: return pgast.ArrayExpr(elements=[ pgast.StringConstant( val=desugar_group.key_name(list(used_args)[0])) ]) using = {k: stmt.using[k] for k in used_args} args = [ pathctx.get_path_var(grouprel, alias_set.path_id, aspect='value', env=ctx.env) for alias_set, _ in using.values() ] # Call grouping on each element we group on to produce a bitmask grouping_alias = ctx.env.aliases.get('g') grouping_call = pgast.FuncCall(name=('grouping', ), args=args) subq = pgast.SelectStmt(target_list=[ pgast.ResTarget(name=grouping_alias, val=grouping_call), ]) q = pgast.SelectStmt(from_clause=[ pgast.RangeSubselect( subquery=subq, alias=pgast.Alias(aliasname=ctx.env.aliases.get())) ]) grouping_ref = pgast.ColumnRef(name=(grouping_alias, )) # Generate a call to ARRAY[...] with a case for each grouping # element, then array_remove out the NULLs. els: List[pgast.BaseExpr] = [] for i, name in enumerate(using): name = desugar_group.key_name(name) mask = 1 << (len(using) - i - 1) # (CASE (e & <mask>) WHEN 0 THEN '<name>' ELSE NULL END) els.append( pgast.CaseExpr( arg=pgast.Expr(kind=pgast.ExprKind.OP, name='&', lexpr=grouping_ref, rexpr=pgast.LiteralExpr(expr=str(mask))), args=[ pgast.CaseWhen(expr=pgast.LiteralExpr(expr='0'), result=pgast.StringConstant(val=name)) ], defresult=pgast.NullConstant())) val = pgast.FuncCall( name=('array_remove', ), args=[pgast.ArrayExpr(elements=els), pgast.NullConstant()]) q.target_list.append(pgast.ResTarget(val=val)) return q