copyFromFileQuery handles a COPY FROM message that is reading from a file, returning any error that occurs
(stmt *node.CopyFrom)
| 720 | |
| 721 | // copyFromFileQuery handles a COPY FROM message that is reading from a file, returning any error that occurs |
| 722 | func (h *ConnectionHandler) copyFromFileQuery(stmt *node.CopyFrom) error { |
| 723 | copyState := ©FromStdinState{ |
| 724 | copyFromStdinNode: stmt, |
| 725 | } |
| 726 | |
| 727 | // TODO: security check for file path |
| 728 | // TODO: Privilege Checking: https://www.postgresql.org/docs/15/sql-copy.html |
| 729 | f, err := os.Open(stmt.File) |
| 730 | if err != nil { |
| 731 | return err |
| 732 | } |
| 733 | defer f.Close() |
| 734 | |
| 735 | _, _, err = h.handleCopyDataHelper(copyState, f) |
| 736 | if err != nil { |
| 737 | return err |
| 738 | } |
| 739 | |
| 740 | sqlCtx, err := h.doltgresHandler.NewContext(context.Background(), h.mysqlConn, "") |
| 741 | if err != nil { |
| 742 | return err |
| 743 | } |
| 744 | |
| 745 | loadDataResults, err := copyState.dataLoader.Finish(sqlCtx) |
| 746 | if err != nil { |
| 747 | return err |
| 748 | } |
| 749 | |
| 750 | if sqlCtx.GetTransaction() != nil && sqlCtx.GetIgnoreAutoCommit() { |
| 751 | txSession, ok := sqlCtx.Session.(sql.TransactionSession) |
| 752 | if !ok { |
| 753 | return errors.Errorf("session does not implement sql.TransactionSession") |
| 754 | } |
| 755 | if err = txSession.CommitTransaction(sqlCtx, txSession.GetTransaction()); err != nil { |
| 756 | return err |
| 757 | } |
| 758 | sqlCtx.SetIgnoreAutoCommit(false) |
| 759 | } |
| 760 | |
| 761 | return h.send(&pgproto3.CommandComplete{ |
| 762 | CommandTag: []byte(fmt.Sprintf("COPY %d", loadDataResults.RowsLoaded)), |
| 763 | }) |
| 764 | } |
| 765 | |
| 766 | // handleCopyDataHelper is a helper function that should only be invoked by handleCopyData. handleCopyData wraps this |
| 767 | // function so that it can capture any returned error message and store it in the saved state. |
no test coverage detected