You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by ab...@apache.org on 2022/09/05 15:30:43 UTC

[incubator-devlake] branch release-v0.13 updated: fix: cached plan must not change result type (SQLSTATE 0A000)

This is an automated email from the ASF dual-hosted git repository.

abeizn pushed a commit to branch release-v0.13
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/release-v0.13 by this push:
     new b483c20f fix: cached plan must not change result type (SQLSTATE 0A000)
b483c20f is described below

commit b483c20f60a867bf631a191a1789d00718484dde
Author: abeizn <zi...@merico.dev>
AuthorDate: Mon Sep 5 11:15:14 2022 +0800

    fix: cached plan must not change result type (SQLSTATE 0A000)
---
 .../migrationscripts/20220716_add_init_tables.go   | 121 ++++++++++++---------
 1 file changed, 71 insertions(+), 50 deletions(-)

diff --git a/plugins/jira/models/migrationscripts/20220716_add_init_tables.go b/plugins/jira/models/migrationscripts/20220716_add_init_tables.go
index 8547d92d..65affff8 100644
--- a/plugins/jira/models/migrationscripts/20220716_add_init_tables.go
+++ b/plugins/jira/models/migrationscripts/20220716_add_init_tables.go
@@ -20,26 +20,28 @@ package migrationscripts
 import (
 	"context"
 	"encoding/base64"
-	"fmt"
 	"strings"
 	"time"
 
 	"github.com/apache/incubator-devlake/config"
+	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/jira/models/migrationscripts/archived"
 	"gorm.io/gorm"
 )
 
-type JiraConnectionTemp struct {
+type JiraConnectionNew struct {
 	archived.RestConnection `mapstructure:",squash"`
 	archived.BasicAuth      `mapstructure:",squash"`
 }
 
-func (JiraConnectionTemp) TableName() string {
-	return "_tool_jira_connections_temp"
+func (JiraConnectionNew) TableName() string {
+	return "_tool_jira_connections_new"
 }
 
-type JiraConnectionV011 struct {
+const JiraConnectionV011 = "_tool_jira_connections"
+
+type JiraConnectionV011Old struct {
 	ID                         uint64    `gorm:"primaryKey" json:"id"`
 	CreatedAt                  time.Time `json:"createdAt"`
 	UpdatedAt                  time.Time `json:"updatedAt"`
@@ -53,15 +55,15 @@ type JiraConnectionV011 struct {
 	RateLimit                  int       `comment:"api request rate limt per hour" json:"rateLimit"`
 }
 
-func (JiraConnectionV011) TableName() string {
-	return "_tool_jira_connections"
+func (JiraConnectionV011Old) TableName() string {
+	return "_tool_jira_connections_old"
 }
 
 type addInitTables struct{}
 
-func (*addInitTables) Up(ctx context.Context, db *gorm.DB) error {
+func (*addInitTables) Up(ctx context.Context, db *gorm.DB) (err error) {
 
-	err := db.Migrator().DropTable(
+	err = db.Migrator().DropTable(
 		// history table
 		"_raw_jira_api_users",
 		"_raw_jira_api_boards",
@@ -92,61 +94,80 @@ func (*addInitTables) Up(ctx context.Context, db *gorm.DB) error {
 		return err
 	}
 
-	// get connection history data
-	err = db.Migrator().CreateTable(&JiraConnectionTemp{})
+	// In order to avoid postgres reporting "cached plan must not change result type",
+	// we have to avoid loading the _tool_jira_connections table before our migration. The trick is to rename it before loading.
+	// so need to use JiraConnectionOld, JiraConnectionNew and JiraConnection to operate.
+	// step1: create _tool_jira_connections_new table
+	// step2: rename _tool_jira_connections to _tool_jira_connections_old
+	// step3: select data from _tool_jira_connections_old and insert date to _tool_jira_connections_new
+	// step4: rename _tool_jira_connections_new to _tool_jira_connections
+
+	// step1
+	err = db.Migrator().CreateTable(&JiraConnectionNew{})
+	if err != nil {
+		return err
+	}
+	defer db.Migrator().DropTable(&JiraConnectionNew{})
+
+	// step2
+	err = db.Migrator().RenameTable("_tool_jira_connections", "_tool_jira_connections_old")
 	if err != nil {
 		return err
 	}
-	defer db.Migrator().DropTable(&JiraConnectionTemp{})
+	defer func() {
+		if err != nil {
+			err = db.Migrator().RenameTable("_tool_jira_connections_old", "_tool_jira_connections")
+		} else {
+			err = db.Migrator().DropTable(&JiraConnectionV011Old{})
+		}
+	}()
 
+	// step3
 	var result *gorm.DB
-	var jiraConns []JiraConnectionV011
+	var jiraConns []JiraConnectionV011Old
 	result = db.Find(&jiraConns)
+	if result.Error != nil {
+		return result.Error
+	}
 
-	if result.Error == nil {
-		for _, v := range jiraConns {
-			conn := &JiraConnectionTemp{}
-			conn.ID = v.ID
-			conn.Name = v.Name
-			conn.Endpoint = v.Endpoint
-			conn.Proxy = v.Proxy
-			conn.RateLimitPerHour = v.RateLimit
-
-			c := config.GetConfig()
-			encKey := c.GetString(core.EncodeKeyEnvStr)
-			if encKey == "" {
-				return fmt.Errorf("jira v0.11 invalid encKey")
-			}
-			auth, err := core.Decrypt(encKey, v.BasicAuthEncoded)
-			if err != nil {
-				return err
-			}
-			pk, err := base64.StdEncoding.DecodeString(auth)
+	for _, v := range jiraConns {
+		conn := &JiraConnectionNew{}
+		conn.ID = v.ID
+		conn.Name = v.Name
+		conn.Endpoint = v.Endpoint
+		conn.Proxy = v.Proxy
+		conn.RateLimitPerHour = v.RateLimit
+
+		c := config.GetConfig()
+		encKey := c.GetString(core.EncodeKeyEnvStr)
+		if encKey == "" {
+			return errors.BadInput.New("jira v0.11 invalid encKey", errors.AsUserMessage())
+		}
+		auth, err := core.Decrypt(encKey, v.BasicAuthEncoded)
+		if err != nil {
+			return err
+		}
+		pk, err := base64.StdEncoding.DecodeString(auth)
+		if err != nil {
+			return err
+		}
+		originInfo := strings.Split(string(pk), ":")
+		if len(originInfo) == 2 {
+			conn.Username = originInfo[0]
+			conn.Password, err = core.Encrypt(encKey, originInfo[1])
 			if err != nil {
 				return err
 			}
-			originInfo := strings.Split(string(pk), ":")
-			if len(originInfo) == 2 {
-				conn.Username = originInfo[0]
-				conn.Password, err = core.Encrypt(encKey, originInfo[1])
-				if err != nil {
-					return err
-				}
-				// create
-				err := db.Create(&conn)
-				if err.Error != nil {
-					return err.Error
-				}
+			// create
+			tx := db.Create(&conn)
+			if tx.Error != nil {
+				return errors.Default.Wrap(tx.Error, "error adding connection to DB")
 			}
 		}
 	}
 
-	err = db.Migrator().DropTable(&JiraConnectionV011{})
-	if err != nil {
-		return err
-	}
-
-	err = db.Migrator().RenameTable(JiraConnectionTemp{}, archived.JiraConnection{})
+	// step4
+	err = db.Migrator().RenameTable("_tool_jira_connections_new", "_tool_jira_connections")
 	if err != nil {
 		return err
 	}