Convert converts the JSON statement into its output form.
()
| 642 | |
| 643 | // Convert converts the JSON statement into its output form. |
| 644 | func (stmt *plpgSQL_stmt_if) Convert() (Block, error) { |
| 645 | // We store all GOTOs that will need to go to the end of the block. Since we can't know that ahead of time, we store |
| 646 | // their indexes and set them at the end of the function. |
| 647 | type gotoEndIndex struct { |
| 648 | BodyIndex int |
| 649 | GotoIndex int32 |
| 650 | } |
| 651 | var gotoEndIndexes []gotoEndIndex |
| 652 | returnBlock := Block{ |
| 653 | Body: []Statement{ |
| 654 | If{ |
| 655 | Condition: stmt.Condition.Expression.Query, |
| 656 | GotoOffset: 2, // The operation following the conditional skips the THEN statements, so we're skipping that |
| 657 | }, |
| 658 | }, |
| 659 | } |
| 660 | // We'll parse our THEN statements, but we won't add them to the block just yet as we need their operation sizes |
| 661 | thenStmts, err := jsonConvertStatements(stmt.Then) |
| 662 | if err != nil { |
| 663 | return Block{}, err |
| 664 | } |
| 665 | // When the condition is false, we want to skip our THEN block, so we do that (plus the GOTO which finishes the THEN block) |
| 666 | returnBlock.Body = append(returnBlock.Body, Goto{Offset: OperationSizeForStatements(thenStmts) + 2}) |
| 667 | // Then we'll append our THEN block |
| 668 | returnBlock.Body = append(returnBlock.Body, thenStmts...) |
| 669 | // Then we want to append the GOTO that finishes the THEN block, but we don't know the end just yet, so we'll save |
| 670 | // its index and fill it in later |
| 671 | gotoEndIndexes = append(gotoEndIndexes, gotoEndIndex{ |
| 672 | BodyIndex: len(returnBlock.Body), |
| 673 | GotoIndex: OperationSizeForStatements(returnBlock.Body), |
| 674 | }) |
| 675 | returnBlock.Body = append(returnBlock.Body, Goto{}) |
| 676 | // We repeat the same process for each ELSIF statement (refer to the comments above) |
| 677 | for _, elseIf := range stmt.ElseIf { |
| 678 | returnBlock.Body = append(returnBlock.Body, If{ |
| 679 | Condition: elseIf.ElseIf.Condition.Expression.Query, |
| 680 | GotoOffset: 2, // Same rules as skipping our THEN statement above |
| 681 | }) |
| 682 | elseIfStmts, err := jsonConvertStatements(elseIf.ElseIf.Then) |
| 683 | if err != nil { |
| 684 | return Block{}, err |
| 685 | } |
| 686 | returnBlock.Body = append(returnBlock.Body, Goto{Offset: OperationSizeForStatements(elseIfStmts) + 2}) |
| 687 | returnBlock.Body = append(returnBlock.Body, elseIfStmts...) |
| 688 | gotoEndIndexes = append(gotoEndIndexes, gotoEndIndex{ |
| 689 | BodyIndex: len(returnBlock.Body), |
| 690 | GotoIndex: OperationSizeForStatements(returnBlock.Body), |
| 691 | }) |
| 692 | returnBlock.Body = append(returnBlock.Body, Goto{}) |
| 693 | } |
| 694 | // Finally we handle our ELSE statements. We don't have a condition to check, so we don't have to append any |
| 695 | // additional GOTOs. |
| 696 | elseStmts, err := jsonConvertStatements(stmt.Else) |
| 697 | if err != nil { |
| 698 | return Block{}, err |
| 699 | } |
| 700 | returnBlock.Body = append(returnBlock.Body, elseStmts...) |
| 701 | // Now we'll set all of our GOTOs so that they skip to the end of the block. |
no test coverage detected