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 }