github.com/dolthub/go-mysql-server@v0.18.0/sql/mysql_db/mysql_db_serialize.go (about) 1 // Copyright 2022 Dolthub, Inc. 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 mysql_db 16 17 import ( 18 flatbuffers "github.com/dolthub/flatbuffers/v23/go" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 "github.com/dolthub/go-mysql-server/sql/mysql_db/serial" 22 ) 23 24 // serializePrivilegeTypes writes the given PrivilegeTypes into the flatbuffer Builder using the given flatbuffer start function, and returns the offset 25 // This helper function is used by PrivilegeSetColumn, PrivilegeSetTable, and PrivilegeSetDatabase 26 func serializePrivilegeTypes(b *flatbuffers.Builder, StartPTVector func(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT, pts []sql.PrivilegeType) flatbuffers.UOffsetT { 27 // Order doesn't matter since it's a set of indexes 28 StartPTVector(b, len(pts)) 29 for _, gs := range pts { 30 b.PrependInt32(int32(gs)) 31 } 32 return b.EndVector(len(pts)) 33 } 34 35 // TODO: should have a generic serialize strings helper method if used in future 36 37 // serializeVectorOffsets writes the given offsets slice to the flatbuffer Builder using the given start vector function, and returns the offset 38 func serializeVectorOffsets(b *flatbuffers.Builder, StartVector func(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT, offsets []flatbuffers.UOffsetT) flatbuffers.UOffsetT { 39 // Expect the given offsets slice to already be in reverse order 40 StartVector(b, len(offsets)) 41 for _, offset := range offsets { 42 b.PrependUOffsetT(offset) 43 } 44 return b.EndVector(len(offsets)) 45 } 46 47 // serializeGlobalDynamic writes the set of dynamic privileges to the flatbuffer builder, and returns offsets of resulting vectors 48 func serializeGlobalDynamic(b *flatbuffers.Builder, dynamicPrivs map[string]bool) (strings flatbuffers.UOffsetT, bools flatbuffers.UOffsetT) { 49 i := 0 50 privStrs := make([]string, len(dynamicPrivs)) 51 serial.PrivilegeSetStartGlobalDynamicWgoVector(b, len(dynamicPrivs)) 52 for priv, withGrantOption := range dynamicPrivs { 53 privStrs[i] = priv 54 b.PrependBool(withGrantOption) 55 i++ 56 } 57 bools = b.EndVector(len(dynamicPrivs)) 58 offsetStrings := make([]flatbuffers.UOffsetT, len(dynamicPrivs)) 59 for i := range privStrs { 60 offsetStrings[i] = b.CreateSharedString(privStrs[i]) 61 } 62 strings = serializeVectorOffsets(b, serial.PrivilegeSetStartGlobalDynamicVector, offsetStrings) 63 return 64 } 65 66 func serializeColumns(b *flatbuffers.Builder, columns []PrivilegeSetColumn) flatbuffers.UOffsetT { 67 // Write column variables, and save offsets 68 offsets := make([]flatbuffers.UOffsetT, len(columns)) 69 for i, column := range columns { 70 name := b.CreateString(column.Name()) 71 privs := serializePrivilegeTypes(b, serial.PrivilegeSetColumnStartPrivsVector, column.ToSlice()) 72 73 serial.PrivilegeSetColumnStart(b) 74 serial.PrivilegeSetColumnAddName(b, name) 75 serial.PrivilegeSetColumnAddPrivs(b, privs) 76 offsets[len(offsets)-i-1] = serial.PrivilegeSetColumnEnd(b) // reverse order 77 } 78 // Write column offsets (already reversed) 79 return serializeVectorOffsets(b, serial.PrivilegeSetTableStartColumnsVector, offsets) 80 } 81 82 func serializeTables(b *flatbuffers.Builder, tables []PrivilegeSetTable) flatbuffers.UOffsetT { 83 // Write table variables, and save offsets 84 offsets := make([]flatbuffers.UOffsetT, len(tables)) 85 for i, table := range tables { 86 name := b.CreateString(table.Name()) 87 privs := serializePrivilegeTypes(b, serial.PrivilegeSetTableStartPrivsVector, table.ToSlice()) 88 cols := serializeColumns(b, table.getColumns()) 89 90 serial.PrivilegeSetTableStart(b) 91 serial.PrivilegeSetTableAddName(b, name) 92 serial.PrivilegeSetTableAddPrivs(b, privs) 93 serial.PrivilegeSetTableAddColumns(b, cols) 94 offsets[len(offsets)-i-1] = serial.PrivilegeSetTableEnd(b) // reverse order 95 } 96 // Write table offsets (order already reversed) 97 return serializeVectorOffsets(b, serial.PrivilegeSetDatabaseStartTablesVector, offsets) 98 } 99 100 func serializeRoutines(b *flatbuffers.Builder, routines []PrivilegeSetRoutine) flatbuffers.UOffsetT { 101 offsets := make([]flatbuffers.UOffsetT, len(routines)) 102 for i, routine := range routines { 103 name := b.CreateString(routine.RoutineName()) 104 privs := serializePrivilegeTypes(b, serial.PrivilegeSetTableStartPrivsVector, routine.ToSlice()) 105 106 serial.PrivilegeSetRoutineStart(b) 107 serial.PrivilegeSetRoutineAddName(b, name) 108 serial.PrivilegeSetRoutineAddPrivs(b, privs) 109 serial.PrivilegeSetRoutineAddIsProc(b, routine.isProc) 110 111 offsets[len(offsets)-i-1] = serial.PrivilegeSetRoutineEnd(b) 112 } 113 114 return serializeVectorOffsets(b, serial.PrivilegeSetDatabaseStartRoutinesVector, offsets) 115 } 116 117 // serializeDatabases writes the given Privilege Set Databases into the flatbuffer Builder, and returns the offset 118 func serializeDatabases(b *flatbuffers.Builder, databases []PrivilegeSetDatabase) flatbuffers.UOffsetT { 119 // Write database variables, and save offsets 120 offsets := make([]flatbuffers.UOffsetT, len(databases)) 121 for i, database := range databases { 122 name := b.CreateString(database.Name()) 123 privs := serializePrivilegeTypes(b, serial.PrivilegeSetDatabaseStartPrivsVector, database.ToSlice()) 124 tables := serializeTables(b, database.getTables()) 125 routines := serializeRoutines(b, database.getRoutines()) 126 127 serial.PrivilegeSetDatabaseStart(b) 128 serial.PrivilegeSetDatabaseAddName(b, name) 129 serial.PrivilegeSetDatabaseAddPrivs(b, privs) 130 serial.PrivilegeSetDatabaseAddTables(b, tables) 131 serial.PrivilegeSetDatabaseAddRoutines(b, routines) 132 offsets[len(offsets)-i-1] = serial.PrivilegeSetDatabaseEnd(b) 133 } 134 135 // Write database offsets (order already reversed) 136 return serializeVectorOffsets(b, serial.PrivilegeSetStartDatabasesVector, offsets) 137 } 138 139 func serializePrivilegeSet(b *flatbuffers.Builder, ps *PrivilegeSet) flatbuffers.UOffsetT { 140 // Write privilege set variables, and save offsets 141 globalStatic := serializePrivilegeTypes(b, serial.PrivilegeSetStartGlobalStaticVector, ps.ToSlice()) 142 globalDynamicStrs, globalDynamicWgos := serializeGlobalDynamic(b, ps.globalDynamic) 143 databases := serializeDatabases(b, ps.getDatabases()) 144 145 // Write PrivilegeSet 146 serial.PrivilegeSetStart(b) 147 serial.PrivilegeSetAddGlobalStatic(b, globalStatic) 148 serial.PrivilegeSetAddGlobalDynamic(b, globalDynamicStrs) 149 serial.PrivilegeSetAddDatabases(b, databases) 150 serial.PrivilegeSetAddGlobalDynamicWgo(b, globalDynamicWgos) 151 return serial.PrivilegeSetEnd(b) 152 } 153 154 // serializeAttributes will deference and write the given string pointer to the flatbuffer builder and will return the 155 // offset. Will return 0 for offset if string pointer is null; this causes the accessor to also return nil when loading 156 func serializeAttributes(b *flatbuffers.Builder, attributes *string) flatbuffers.UOffsetT { 157 if attributes == nil { 158 return 0 159 } else { 160 return b.CreateString(*attributes) 161 } 162 } 163 164 func serializeUser(b *flatbuffers.Builder, users []*User) flatbuffers.UOffsetT { 165 // Write user variables, and save offsets 166 offsets := make([]flatbuffers.UOffsetT, len(users)) 167 for i, user := range users { 168 userName := b.CreateString(user.User) 169 host := b.CreateString(user.Host) 170 privilegeSet := serializePrivilegeSet(b, &user.PrivilegeSet) 171 plugin := b.CreateString(user.Plugin) 172 password := b.CreateString(user.Password) 173 attributes := serializeAttributes(b, user.Attributes) 174 identity := b.CreateString(user.Identity) 175 176 serial.UserStart(b) 177 serial.UserAddUser(b, userName) 178 serial.UserAddHost(b, host) 179 serial.UserAddPrivilegeSet(b, privilegeSet) 180 serial.UserAddPlugin(b, plugin) 181 serial.UserAddPassword(b, password) 182 serial.UserAddPasswordLastChanged(b, user.PasswordLastChanged.Unix()) 183 serial.UserAddLocked(b, user.Locked) 184 serial.UserAddAttributes(b, attributes) 185 serial.UserAddIdentity(b, identity) 186 187 offsets[len(users)-i-1] = serial.UserEnd(b) // reverse order 188 } 189 190 // Write user offsets (already in reverse order) 191 return serializeVectorOffsets(b, serial.MySQLDbStartUserVector, offsets) 192 } 193 194 func serializeRoleEdge(b *flatbuffers.Builder, roleEdges []*RoleEdge) flatbuffers.UOffsetT { 195 offsets := make([]flatbuffers.UOffsetT, len(roleEdges)) 196 for i, roleEdge := range roleEdges { 197 // Serialize each of the member vars in RoleEdge and save their offsets 198 fromHost := b.CreateString(roleEdge.FromHost) 199 fromUser := b.CreateString(roleEdge.FromUser) 200 toHost := b.CreateString(roleEdge.ToHost) 201 toUser := b.CreateString(roleEdge.ToUser) 202 203 // Start RoleEdge 204 serial.RoleEdgeStart(b) 205 206 // Write their offsets to flatbuffer builder 207 serial.RoleEdgeAddFromHost(b, fromHost) 208 serial.RoleEdgeAddFromUser(b, fromUser) 209 serial.RoleEdgeAddToHost(b, toHost) 210 serial.RoleEdgeAddToUser(b, toUser) 211 212 // Write WithAdminOption (boolean value doesn't need offset) 213 serial.RoleEdgeAddWithAdminOption(b, roleEdge.WithAdminOption) 214 215 // End RoleEdge 216 offsets[len(roleEdges)-i-1] = serial.RoleEdgeEnd(b) // reverse order 217 } 218 219 // Write role_edges vector (already in reversed order) 220 return serializeVectorOffsets(b, serial.MySQLDbStartRoleEdgesVector, offsets) 221 } 222 223 func serializeReplicaSourceInfo(b *flatbuffers.Builder, replicaSourceInfos []*ReplicaSourceInfo) flatbuffers.UOffsetT { 224 offsets := make([]flatbuffers.UOffsetT, len(replicaSourceInfos)) 225 226 for i, replicaSourceInfo := range replicaSourceInfos { 227 host := b.CreateString(replicaSourceInfo.Host) 228 user := b.CreateString(replicaSourceInfo.User) 229 password := b.CreateString(replicaSourceInfo.Password) 230 uuid := b.CreateString(replicaSourceInfo.Uuid) 231 232 // Start ReplicaSourceInfo 233 serial.ReplicaSourceInfoStart(b) 234 235 // Write their offsets to flatbuffer builder 236 serial.ReplicaSourceInfoAddHost(b, host) 237 serial.ReplicaSourceInfoAddUser(b, user) 238 serial.ReplicaSourceInfoAddPassword(b, password) 239 serial.ReplicaSourceInfoAddUuid(b, uuid) 240 241 // Write non-string fields (uint value doesn't need offset) 242 serial.ReplicaSourceInfoAddPort(b, replicaSourceInfo.Port) 243 serial.ReplicaSourceInfoAddConnectRetryInterval(b, replicaSourceInfo.ConnectRetryInterval) 244 serial.ReplicaSourceInfoAddConnectRetryCount(b, replicaSourceInfo.ConnectRetryCount) 245 246 // End ReplicaSourceInfo 247 offsets[len(replicaSourceInfos)-i-1] = serial.ReplicaSourceInfoEnd(b) 248 } 249 250 // Write replica source info vector (already in reversed order) 251 return serializeVectorOffsets(b, serial.MySQLDbStartReplicaSourceInfoVector, offsets) 252 }