зеркало из https://github.com/github/vitess-gh.git
allow sql_mode or json_mode on the server-side
Signed-off-by: Alex Charis <alex.charis@shopify.com>
This commit is contained in:
Родитель
5c85d70633
Коммит
6632d48cc0
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче