Next implements the interface sql.RowIter.
(ctx *sql.Context)
| 197 | |
| 198 | // Next implements the interface sql.RowIter. |
| 199 | func (t *triggerExecutionIter) Next(ctx *sql.Context) (sql.Row, error) { |
| 200 | nextRow, err := t.source.Next(ctx) |
| 201 | if err != nil { |
| 202 | return nextRow, err |
| 203 | } |
| 204 | var oldRow sql.Row |
| 205 | var newRow sql.Row |
| 206 | switch t.split { |
| 207 | case TriggerExecutionRowHandling_Old: |
| 208 | oldRow = nextRow |
| 209 | case TriggerExecutionRowHandling_OldNew: |
| 210 | oldRow = nextRow[:len(t.sch)] |
| 211 | newRow = nextRow[len(t.sch):] |
| 212 | case TriggerExecutionRowHandling_NewOld: |
| 213 | newRow = nextRow[:len(t.sch)] |
| 214 | oldRow = nextRow[len(t.sch):] |
| 215 | case TriggerExecutionRowHandling_New: |
| 216 | newRow = nextRow |
| 217 | } |
| 218 | |
| 219 | // TODO: handle other special variables |
| 220 | triggerVars := make(map[string]any) |
| 221 | if t.tgOp != "" { |
| 222 | triggerVars["TG_OP"] = t.tgOp |
| 223 | } |
| 224 | |
| 225 | for funcIdx, function := range t.functions { |
| 226 | if t.whens[funcIdx].ID.IsValid() { |
| 227 | whenValue, err := plpgsql.TriggerCall(ctx, t.whens[funcIdx], t.runner, t.sch, oldRow, newRow, triggerVars) |
| 228 | if err != nil { |
| 229 | if strings.Contains(err.Error(), "no valid cast for return value") { |
| 230 | // TODO: this error should technically be caught during parsing, but interpreted functions don't |
| 231 | // have the ability to determine types during parsing yet (also applies to the same error below) |
| 232 | return nil, fmt.Errorf("argument of WHEN must be type boolean") |
| 233 | } |
| 234 | return nil, err |
| 235 | } |
| 236 | whenBool, ok := whenValue.(bool) |
| 237 | if !ok { |
| 238 | return nil, fmt.Errorf("argument of WHEN must be type boolean") |
| 239 | } |
| 240 | if !whenBool { |
| 241 | continue |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | returnedValue, err := plpgsql.TriggerCall(ctx, function, t.runner, t.sch, oldRow, newRow, triggerVars) |
| 246 | if err != nil { |
| 247 | return nil, err |
| 248 | } |
| 249 | |
| 250 | if returnedValue == nil { |
| 251 | // a returned value of NULL on a BEFORE trigger means to not modify the row, so we return a signal error |
| 252 | if t.timing == triggers.TriggerTiming_Before { |
| 253 | return nil, sql.ErrRowEditCanceled.New() |
| 254 | } else { |
| 255 | return nextRow, nil |
| 256 | } |
nothing calls this directly
no test coverage detected