CallSqlFunction runs the given SQL definition inside the function on the given runner.
(ctx *sql.Context, f SQLFunction, runner sql.StatementRunner, args []any)
| 101 | |
| 102 | // CallSqlFunction runs the given SQL definition inside the function on the given runner. |
| 103 | func CallSqlFunction(ctx *sql.Context, f SQLFunction, runner sql.StatementRunner, args []any) (any, error) { |
| 104 | paramMap := make(map[string]*ParamTypAndValue) |
| 105 | for i, name := range f.ParameterNames { |
| 106 | if name == "" { |
| 107 | // This allows for positional references such as $1, $2, etc. |
| 108 | name = fmt.Sprintf("$%d", i+1) |
| 109 | } |
| 110 | paramMap[name] = &ParamTypAndValue{ |
| 111 | Typ: f.ParameterTypes[i], |
| 112 | Val: args[i], |
| 113 | FromCreate: false, |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | if lower := strings.ToLower(f.SqlStatement); strings.HasPrefix(lower, "return") { |
| 118 | f.SqlStatement = fmt.Sprintf("SELECT%s", f.SqlStatement[6:]) |
| 119 | } |
| 120 | |
| 121 | parseds, err := parser.Parse(f.SqlStatement) |
| 122 | if err != nil { |
| 123 | return "", err |
| 124 | } |
| 125 | |
| 126 | if len(parseds) > 1 { |
| 127 | // of multiple statements, the function returns the result of the final statement in the execution block |
| 128 | var res any |
| 129 | for _, parsed := range parseds { |
| 130 | err = ReplaceFunctionColumn(parsed.AST, paramMap) |
| 131 | if err != nil { |
| 132 | return nil, err |
| 133 | } |
| 134 | convertedAST, err := convertToVitess(parsed) |
| 135 | if err != nil { |
| 136 | return nil, err |
| 137 | } |
| 138 | res, err = sql.RunInterpreted(ctx, func(subCtx *sql.Context) (any, error) { |
| 139 | sch, rowIter, _, err := runner.QueryWithBindings(ctx, parsed.AST.String(), convertedAST, nil, nil) |
| 140 | if err != nil { |
| 141 | return nil, err |
| 142 | } |
| 143 | rows, err := sql.RowIterToRows(subCtx, rowIter) |
| 144 | if err != nil { |
| 145 | return nil, err |
| 146 | } |
| 147 | if len(sch) != 1 { |
| 148 | return nil, errors.New("expression does not result in a single value") |
| 149 | } |
| 150 | if len(rows) != 1 { |
| 151 | return nil, errors.New("expression returned multiple result sets") |
| 152 | } |
| 153 | if len(rows[0]) != 1 { |
| 154 | return nil, errors.New("expression returned multiple results") |
| 155 | } |
| 156 | return rows[0][0], nil |
| 157 | }) |
| 158 | if err != nil { |
| 159 | return nil, err |
| 160 | } |
no test coverage detected