Convert converts the JSON statement into its output form.
()
| 517 | |
| 518 | // Convert converts the JSON statement into its output form. |
| 519 | func (stmt *plpgSQL_stmt_fori) Convert() (block Block, err error) { |
| 520 | block.Label = stmt.Label |
| 521 | block.IsLoop = true |
| 522 | |
| 523 | if stmt.Var.Variable == nil { |
| 524 | return Block{}, errors.New("for loop variable cannot be nil") |
| 525 | } |
| 526 | varName := stmt.Var.Variable.RefName |
| 527 | |
| 528 | // Extract bound and step expressions |
| 529 | lowerExpr := "1" |
| 530 | if stmt.Lower != nil { |
| 531 | lowerExpr = stmt.Lower.Expression.Query |
| 532 | } |
| 533 | upperExpr := "1" |
| 534 | if stmt.Upper != nil { |
| 535 | upperExpr = stmt.Upper.Expression.Query |
| 536 | } |
| 537 | stepExpr := "1" |
| 538 | if stmt.Step != nil { |
| 539 | stepExpr = stmt.Step.Expression.Query |
| 540 | } |
| 541 | |
| 542 | // Determine init value, loop condition, and increment expression based on direction. |
| 543 | // In the JSON, Lower is always the starting value and Upper is the ending bound. |
| 544 | var condition, incrExpr string |
| 545 | if stmt.Reverse { |
| 546 | condition = fmt.Sprintf("%s >= (%s)", varName, upperExpr) |
| 547 | incrExpr = fmt.Sprintf("%s - (%s)", varName, stepExpr) |
| 548 | } else { |
| 549 | condition = fmt.Sprintf("%s <= (%s)", varName, upperExpr) |
| 550 | incrExpr = fmt.Sprintf("%s + (%s)", varName, stepExpr) |
| 551 | } |
| 552 | |
| 553 | // Convert the loop body. |
| 554 | convertedBody, err := jsonConvertStatements(stmt.Body) |
| 555 | if err != nil { |
| 556 | return Block{}, err |
| 557 | } |
| 558 | bodySize := OperationSizeForStatements(convertedBody) |
| 559 | |
| 560 | // Build the loop body: |
| 561 | // [0] InitAssign: varName := lower |
| 562 | // [1] If(condition, GotoOffset:2) → jumps to [3] (first body stmt) when true |
| 563 | // [2] ExitGoto → offset=3+bodySize → jumps to ScopeEnd |
| 564 | // [3..3+N-1] body statements (N = bodySize) |
| 565 | // [3+N] IncrAssign: varName := varName +/- step |
| 566 | // [3+N+1] BackGoto → offset=-(3+bodySize) → jumps back to If at [1] |
| 567 | // |
| 568 | // Because no variables are declared in this block (the loop variable is already |
| 569 | // declared by the caller's DECLARE section), ScopeBegin is at M and the |
| 570 | // InitAssign is at M+1, so all offsets are consistent. |
| 571 | block.Body = []Statement{ |
| 572 | Assignment{ |
| 573 | VariableName: varName, |
| 574 | Expression: lowerExpr, |
| 575 | }, |
| 576 | If{ |
nothing calls this directly
no test coverage detected