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  }