github.com/matrixorigin/matrixone@v1.2.0/pkg/bootstrap/versions/version.go (about)

     1  // Copyright 2024 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package versions
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	"github.com/fagongzi/util/format"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/catalog"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/util/executor"
    26  )
    27  
    28  func (v Version) IsReady() bool {
    29  	return v.State == StateReady
    30  }
    31  
    32  func (v Version) IsUpgradingTenant() bool {
    33  	return v.State == StateUpgradingTenant
    34  }
    35  
    36  func (v Version) NeedUpgradeCluster() bool {
    37  	return v.UpgradeCluster == Yes
    38  }
    39  
    40  func (v Version) NeedUpgradeTenant() bool {
    41  	return v.UpgradeTenant == Yes
    42  }
    43  
    44  func (v Version) CanDirectUpgrade(version string) bool {
    45  	return Compare(v.MinUpgradeVersion, version) <= 0
    46  }
    47  
    48  func (v Version) GetInitVersionSQL(state int32) string {
    49  	return fmt.Sprintf(`insert into %s values ('%s', %d, %d, current_timestamp(), current_timestamp())`,
    50  		catalog.MOVersionTable,
    51  		v.MinUpgradeVersion,
    52  		0,
    53  		state,
    54  	)
    55  }
    56  
    57  func AddVersion(
    58  	version string,
    59  	versionOffset uint32,
    60  	state int32,
    61  	txn executor.TxnExecutor) error {
    62  	sql := fmt.Sprintf(`insert into %s values ('%s', %d, %d, current_timestamp(), current_timestamp())`,
    63  		catalog.MOVersionTable,
    64  		version,
    65  		versionOffset,
    66  		state)
    67  	res, err := txn.Exec(sql, executor.StatementOption{})
    68  	if err != nil {
    69  		return err
    70  	}
    71  	res.Close()
    72  	return nil
    73  }
    74  
    75  func GetLatestVersion(txn executor.TxnExecutor) (Version, error) {
    76  	sql := fmt.Sprintf(`select version, version_offset, state from %s order by create_at desc limit 1`, catalog.MOVersionTable)
    77  	res, err := txn.Exec(sql, executor.StatementOption{})
    78  	if err != nil {
    79  		return Version{}, err
    80  	}
    81  	defer res.Close()
    82  
    83  	var version Version
    84  	res.ReadRows(func(rows int, cols []*vector.Vector) bool {
    85  		version.Version = cols[0].GetStringAt(0)
    86  		version.VersionOffset = vector.GetFixedAt[uint32](cols[1], 0)
    87  		version.State = vector.GetFixedAt[int32](cols[2], 0)
    88  		return true
    89  	})
    90  	return version, nil
    91  }
    92  
    93  func GetLatestUpgradeVersion(txn executor.TxnExecutor) (Version, error) {
    94  	sql := fmt.Sprintf(`select version from %s where state != %d order by create_at desc limit 1`,
    95  		catalog.MOVersionTable,
    96  		StateReady)
    97  	res, err := txn.Exec(sql, executor.StatementOption{})
    98  	if err != nil {
    99  		return Version{}, err
   100  	}
   101  	defer res.Close()
   102  
   103  	var version Version
   104  	res.ReadRows(func(rows int, cols []*vector.Vector) bool {
   105  		version.Version = cols[0].GetStringAt(0)
   106  		return true
   107  	})
   108  	return version, nil
   109  }
   110  
   111  func MustGetLatestReadyVersion(
   112  	txn executor.TxnExecutor) (string, error) {
   113  	sql := fmt.Sprintf(`select version from %s 
   114  			where state = %d 
   115  			order by create_at desc limit 1`,
   116  		catalog.MOVersionTable,
   117  		StateReady)
   118  
   119  	res, err := txn.Exec(sql, executor.StatementOption{})
   120  	if err != nil {
   121  		return "", err
   122  	}
   123  	defer res.Close()
   124  
   125  	version := ""
   126  	res.ReadRows(func(rows int, cols []*vector.Vector) bool {
   127  		version = cols[0].GetStringAt(0)
   128  		return true
   129  	})
   130  	if version == "" {
   131  		panic("missing latest ready version")
   132  	}
   133  	return version, nil
   134  }
   135  
   136  func GetVersionState(
   137  	version string,
   138  	versionOffset uint32,
   139  	txn executor.TxnExecutor,
   140  	forUpdate bool) (int32, bool, error) {
   141  	withForUpdate := ""
   142  	if forUpdate {
   143  		withForUpdate = "for update"
   144  	}
   145  	sql := fmt.Sprintf(`select state from %s where version = '%s' and version_offset = %d %s`,
   146  		catalog.MOVersionTable,
   147  		version,
   148  		versionOffset,
   149  		withForUpdate)
   150  
   151  	res, err := txn.Exec(sql, executor.StatementOption{})
   152  	if err != nil {
   153  		return 0, false, err
   154  	}
   155  	defer res.Close()
   156  
   157  	state := int32(0)
   158  	loaded := false
   159  	n := 0
   160  	res.ReadRows(func(rows int, cols []*vector.Vector) bool {
   161  		state = vector.GetFixedAt[int32](cols[0], 0)
   162  		loaded = true
   163  		n++
   164  		return true
   165  	})
   166  	if loaded && n > 1 {
   167  		panic("BUG: missing version " + version)
   168  	}
   169  	return state, loaded, nil
   170  }
   171  
   172  func UpdateVersionState(
   173  	version string,
   174  	versionOffset uint32,
   175  	state int32,
   176  	txn executor.TxnExecutor) error {
   177  	sql := fmt.Sprintf("update %s set state = %d, update_at = current_timestamp() where version = '%s' and version_offset = %d",
   178  		catalog.MOVersionTable,
   179  		state,
   180  		version,
   181  		versionOffset)
   182  	res, err := txn.Exec(sql, executor.StatementOption{})
   183  	if err != nil {
   184  		return err
   185  	}
   186  	res.Close()
   187  	return nil
   188  }
   189  
   190  func Compare(v1, v2 string) int {
   191  	x1, y1, z1 := parseVersion(v1)
   192  	x2, y2, z2 := parseVersion(v2)
   193  
   194  	if x1 > x2 {
   195  		return 1
   196  	} else if x1 < x2 {
   197  		return -1
   198  	}
   199  
   200  	if y1 > y2 {
   201  		return 1
   202  	} else if y1 < y2 {
   203  		return -1
   204  	}
   205  
   206  	return z1 - z2
   207  }
   208  
   209  // x.y.z
   210  func parseVersion(version string) (int, int, int) {
   211  	fields := strings.SplitN(version, ".", 3)
   212  	return format.MustParseStringInt(fields[0]),
   213  		format.MustParseStringInt(fields[1]),
   214  		format.MustParseStringInt(fields[2])
   215  }
   216  
   217  func IsFrameworkTablesCreated(txn executor.TxnExecutor) (bool, error) {
   218  	// Check if the `mo_version` table exists
   219  	tableExist, err := CheckTableDefinition(txn, catalog.System_Account, catalog.MO_CATALOG, catalog.MOVersionTable)
   220  	if err != nil {
   221  		return false, err
   222  	}
   223  
   224  	// If the `mo_version` table exists
   225  	if tableExist {
   226  		return true, nil
   227  	}
   228  	// Return the status of the framework table that has not been created
   229  	return false, nil
   230  }
   231  
   232  // FetchAllTenants get all tenantIDs in mo system, including system tenants
   233  func FetchAllTenants(txn executor.TxnExecutor) ([]int32, error) {
   234  	ids := make([]int32, 0, 10)
   235  	sql := "select account_id from mo_account where account_id >= 0 order by account_id"
   236  	res, err := txn.Exec(sql, executor.StatementOption{})
   237  	if err != nil {
   238  		return ids, err
   239  	}
   240  
   241  	res.ReadRows(func(rows int, cols []*vector.Vector) bool {
   242  		for i := 0; i < rows; i++ {
   243  			last := vector.GetFixedAt[int32](cols[0], i)
   244  			ids = append(ids, last)
   245  		}
   246  		return true
   247  	})
   248  	res.Close()
   249  	return ids, nil
   250  }