allow sql_mode or json_mode on the server-side

Signed-off-by: Alex Charis <alex.charis@shopify.com>
This commit is contained in:
Alex Charis 2021-06-03 18:33:56 +00:00
Родитель 5c85d70633
Коммит 6632d48cc0
5 изменённых файлов: 701 добавлений и 599 удалений

Просмотреть файл

@ -24,9 +24,6 @@ import (
"vitess.io/vitess/go/cmd/vtctldclient/cli"
"vitess.io/vitess/go/json2"
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/topo"
"vitess.io/vitess/go/vt/topotools"
vschemapb "vitess.io/vitess/go/vt/proto/vschema"
vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata"
@ -41,9 +38,11 @@ var (
}
// ApplyVSchema makes an ApplyVSchema gRPC call to a vtctld.
ApplyVSchema = &cobra.Command{
Use: "ApplyVSchema {-vschema=<vschema> || -vschema_file=<vschema file> || -sql=<sql> || -sql_file=<sql file>} [-cells=c1,c2,...] [-skip_rebuild] [-dry-run] <keyspace>",
Args: cobra.ExactArgs(1),
RunE: commandApplyVSchema,
Use: "ApplyVSchema {-vschema=<vschema> || -vschema_file=<vschema file> || -sql=<sql> || -sql_file=<sql file>} [-cells=c1,c2,...] [-skip_rebuild] [-dry-run] <keyspace>",
Args: cobra.ExactArgs(1),
DisableFlagsInUseLine: true,
RunE: commandApplyVSchema,
Short: "Applies the VTGate routing schema to the provided keyspace. Shows the result after application.",
}
)
@ -58,11 +57,6 @@ var applyVSchemaOptions = struct {
}{}
func commandApplyVSchema(cmd *cobra.Command, args []string) error {
keyspace := cmd.Flags().Arg(0) // validated on the server-side
var vs *vschemapb.Keyspace
var err error
sqlMode := (applyVSchemaOptions.SQL != "") != (applyVSchemaOptions.SQLFile != "")
jsonMode := (applyVSchemaOptions.VSchema != "") != (applyVSchemaOptions.VSchemaFile != "")
@ -74,36 +68,24 @@ func commandApplyVSchema(cmd *cobra.Command, args []string) error {
return fmt.Errorf("one of the sql, sql_file, vschema, or vschema_file flags must be specified when calling the ApplyVSchema command")
}
req := &vtctldatapb.ApplyVSchemaRequest{
Keyspace: cmd.Flags().Arg(0),
SkipRebuild: applyVSchemaOptions.SkipRebuild,
Cells: applyVSchemaOptions.Cells,
DryRun: applyVSchemaOptions.DryRun,
}
var err error
if sqlMode {
if applyVSchemaOptions.SQLFile != "" {
sqlBytes, err := ioutil.ReadFile(applyVSchemaOptions.SQLFile)
if err != nil {
return err
}
applyVSchemaOptions.SQL = string(sqlBytes)
req.Sql = string(sqlBytes)
} else {
req.Sql = applyVSchemaOptions.SQL
}
stmt, err := sqlparser.Parse(applyVSchemaOptions.SQL)
if err != nil {
return fmt.Errorf("error parsing VSchema statement `%s`: %v", applyVSchemaOptions.SQL, err)
}
ddl, ok := stmt.(*sqlparser.AlterVschema)
if !ok {
return fmt.Errorf("error parsing VSchema statement `%s`: not a ddl statement", applyVSchemaOptions.SQL)
}
resp, err := client.GetVSchema(commandCtx, &vtctldatapb.GetVSchemaRequest{
Keyspace: keyspace,
})
if err != nil && !topo.IsErrType(err, topo.NoNode) {
return err
} // otherwise, we keep the empty vschema object from above
vs, err = topotools.ApplyVSchemaDDL(keyspace, resp.VSchema, ddl)
if err != nil {
return err
}
} else { // jsonMode
var schema []byte
if applyVSchemaOptions.VSchemaFile != "" {
@ -115,30 +97,17 @@ func commandApplyVSchema(cmd *cobra.Command, args []string) error {
schema = []byte(applyVSchemaOptions.VSchema)
}
vs = &vschemapb.Keyspace{}
var vs *vschemapb.Keyspace
err = json2.Unmarshal(schema, vs)
if err != nil {
return err
}
req.VSchema = vs
}
cli.FinishedParsing(cmd)
if applyVSchemaOptions.DryRun {
data, err := cli.MarshalJSON(vs)
if err != nil {
return err
}
fmt.Printf("Dry run: Skipping update of VSchema. New VSchema would be: %s\n", data)
return nil
}
res, err := client.ApplyVSchema(commandCtx, &vtctldatapb.ApplyVSchemaRequest{
Keyspace: keyspace,
VSchema: vs,
SkipRebuild: applyVSchemaOptions.SkipRebuild,
Cells: applyVSchemaOptions.Cells,
})
res, err := client.ApplyVSchema(commandCtx, req)
if err != nil {
return err
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1078,24 +1078,12 @@ func (m *ApplyVSchemaRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.Cells) > 0 {
for iNdEx := len(m.Cells) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Cells[iNdEx])
copy(dAtA[i:], m.Cells[iNdEx])
i = encodeVarint(dAtA, i, uint64(len(m.Cells[iNdEx])))
i--
dAtA[i] = 0x22
}
}
if m.SkipRebuild {
if len(m.Sql) > 0 {
i -= len(m.Sql)
copy(dAtA[i:], m.Sql)
i = encodeVarint(dAtA, i, uint64(len(m.Sql)))
i--
if m.SkipRebuild {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x18
dAtA[i] = 0x32
}
if m.VSchema != nil {
{
@ -1107,7 +1095,36 @@ func (m *ApplyVSchemaRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i = encodeVarint(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
dAtA[i] = 0x2a
}
if len(m.Cells) > 0 {
for iNdEx := len(m.Cells) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Cells[iNdEx])
copy(dAtA[i:], m.Cells[iNdEx])
i = encodeVarint(dAtA, i, uint64(len(m.Cells[iNdEx])))
i--
dAtA[i] = 0x22
}
}
if m.DryRun {
i--
if m.DryRun {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x18
}
if m.SkipRebuild {
i--
if m.SkipRebuild {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x10
}
if len(m.Keyspace) > 0 {
i -= len(m.Keyspace)
@ -5336,19 +5353,26 @@ func (m *ApplyVSchemaRequest) SizeVT() (n int) {
if l > 0 {
n += 1 + l + sov(uint64(l))
}
if m.VSchema != nil {
l = m.VSchema.SizeVT()
n += 1 + l + sov(uint64(l))
}
if m.SkipRebuild {
n += 2
}
if m.DryRun {
n += 2
}
if len(m.Cells) > 0 {
for _, s := range m.Cells {
l = len(s)
n += 1 + l + sov(uint64(l))
}
}
if m.VSchema != nil {
l = m.VSchema.SizeVT()
n += 1 + l + sov(uint64(l))
}
l = len(m.Sql)
if l > 0 {
n += 1 + l + sov(uint64(l))
}
if m.unknownFields != nil {
n += len(m.unknownFields)
}
@ -9435,6 +9459,78 @@ func (m *ApplyVSchemaRequest) UnmarshalVT(dAtA []byte) error {
m.Keyspace = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field SkipRebuild", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.SkipRebuild = bool(v != 0)
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DryRun", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.DryRun = bool(v != 0)
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLength
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field VSchema", wireType)
}
@ -9470,29 +9566,9 @@ func (m *ApplyVSchemaRequest) UnmarshalVT(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field SkipRebuild", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.SkipRebuild = bool(v != 0)
case 4:
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cells", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Sql", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
@ -9520,7 +9596,7 @@ func (m *ApplyVSchemaRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex]))
m.Sql = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex

Просмотреть файл

@ -37,6 +37,7 @@ import (
"vitess.io/vitess/go/vt/logutil"
"vitess.io/vitess/go/vt/mysqlctl/backupstorage"
"vitess.io/vitess/go/vt/mysqlctl/mysqlctlproto"
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/topo"
"vitess.io/vitess/go/vt/topo/topoproto"
"vitess.io/vitess/go/vt/topotools"
@ -132,22 +133,57 @@ func (s *VtctldServer) ApplyRoutingRules(ctx context.Context, req *vtctldatapb.A
func (s *VtctldServer) ApplyVSchema(ctx context.Context, req *vtctldatapb.ApplyVSchemaRequest) (*vtctldatapb.ApplyVSchemaResponse, error) {
if _, err := s.ts.GetKeyspace(ctx, req.Keyspace); err != nil {
if topo.IsErrType(err, topo.NoNode) {
return nil, fmt.Errorf("keyspace(%s) doesn't exist, check if the keyspace is initialized", req.Keyspace)
return nil, vterrors.Wrapf(err, "keyspace(%s) doesn't exist, check if the keyspace is initialized", req.Keyspace)
}
return nil, fmt.Errorf("GetKeyspace(%s) = %w", req.Keyspace, err)
return nil, vterrors.Wrapf(err, "GetKeyspace(%s)", req.Keyspace)
}
if err := s.ts.SaveVSchema(ctx, req.Keyspace, req.VSchema); err != nil {
return nil, fmt.Errorf("SaveVSchema(%s, %v) = %w", req.Keyspace, req.VSchema, err)
if (req.Sql != "" && req.VSchema != nil) || (req.Sql == "" && req.VSchema == nil) {
return nil, vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "must pass exactly one of req.VSchema and req.Sql")
}
var vs *vschemapb.Keyspace
var err error
if req.Sql != "" {
stmt, err := sqlparser.Parse(req.Sql)
if err != nil {
return nil, vterrors.Wrapf(err, "Parse(%s)", req.Sql)
}
ddl, ok := stmt.(*sqlparser.AlterVschema)
if !ok {
return nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "error parsing VSchema DDL statement `%s`", req.Sql)
}
vs, err = s.ts.GetVSchema(ctx, req.Keyspace)
if err != nil && !topo.IsErrType(err, topo.NoNode) {
return nil, vterrors.Wrapf(err, "GetVSchema(%s)", req.Keyspace)
} // otherwise, we keep the empty vschema object from above
vs, err = topotools.ApplyVSchemaDDL(req.Keyspace, vs, ddl)
if err != nil {
return nil, vterrors.Wrapf(err, "ApplyVSchemaDDL(%s,%v,%v)", req.Keyspace, vs, ddl)
}
} else { // "jsonMode"
vs = req.VSchema
}
if req.DryRun {
return &vtctldatapb.ApplyVSchemaResponse{VSchema: vs}, nil
}
if err = s.ts.SaveVSchema(ctx, req.Keyspace, vs); err != nil {
return nil, vterrors.Wrapf(err, "SaveVSchema(%s, %v)", req.Keyspace, req.VSchema)
}
if !req.SkipRebuild {
if err := s.ts.RebuildSrvVSchema(ctx, req.Cells); err != nil {
return nil, fmt.Errorf("RebuildSrvVSchema = %w", err)
return nil, vterrors.Wrapf(err, "RebuildSrvVSchema")
}
}
updatedVS, err := s.ts.GetVSchema(ctx, req.Keyspace)
if err != nil {
return nil, fmt.Errorf("GetKeyspace(%s) = %w", req.Keyspace, err)
return nil, vterrors.Wrapf(err, "GetVSchema(%s)", req.Keyspace)
}
return &vtctldatapb.ApplyVSchemaResponse{VSchema: updatedVS}, nil
}

Просмотреть файл

@ -161,9 +161,11 @@ message ApplyRoutingRulesResponse {
message ApplyVSchemaRequest {
string keyspace = 1;
vschema.Keyspace v_schema = 2;
bool skip_rebuild = 3;
bool skip_rebuild = 2;
bool dry_run = 3;
repeated string cells = 4;
vschema.Keyspace v_schema = 5;
string sql = 6;
}
message ApplyVSchemaResponse {