github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/chaos/cases/stmt.go (about)

     1  // Copyright 2020 PingCAP, 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package main
    15  
    16  import (
    17  	"math/rand"
    18  
    19  	"github.com/chaos-mesh/go-sqlsmith"
    20  	"github.com/pingcap/tidb/pkg/parser"
    21  	"github.com/pingcap/tidb/pkg/parser/ast"
    22  )
    23  
    24  type dmlType int
    25  
    26  const (
    27  	insertDML dmlType = iota + 1
    28  	updateDML
    29  	deleteDML
    30  )
    31  
    32  // randDML generates DML (INSERT, UPDATE or DELETE).
    33  // insert:update:delete=2:1:1
    34  func randDML(ss *sqlsmith.SQLSmith) (dml string, t dmlType, err error) {
    35  	t = dmlType(rand.Intn(4) + 1)
    36  	switch t {
    37  	case updateDML:
    38  		dml, _, err = ss.UpdateStmt()
    39  	case deleteDML:
    40  		dml, _, err = ss.DeleteStmt()
    41  	default:
    42  		t = insertDML
    43  		dml, _, err = ss.InsertStmt(false)
    44  	}
    45  	return
    46  }
    47  
    48  // randDDL generates `ALTER TABLE` DDL.
    49  func randDDL(ss *sqlsmith.SQLSmith) (string, error) {
    50  	for {
    51  		sql, err := ss.AlterTableStmt(&sqlsmith.DDLOptions{
    52  			OnlineDDL: false,
    53  			Tables:    make([]string, 0),
    54  		})
    55  
    56  		if err != nil {
    57  			return sql, err
    58  		} else if !isValidSQL(sql) {
    59  			continue
    60  		}
    61  
    62  		return sql, nil
    63  	}
    64  }
    65  
    66  func isValidSQL(sql string) bool {
    67  	_, err := parser.New().ParseOneStmt(sql, "", "")
    68  	return err == nil
    69  }
    70  
    71  func isNotNullNonDefaultAddCol(sql string) (bool, error) {
    72  	stmt, err := parser.New().ParseOneStmt(sql, "", "")
    73  	if err != nil {
    74  		return false, err
    75  	}
    76  	v, ok := stmt.(*ast.AlterTableStmt)
    77  	if !ok {
    78  		return false, nil
    79  	}
    80  
    81  	if len(v.Specs) == 0 || v.Specs[0].Tp != ast.AlterTableAddColumns || len(v.Specs[0].NewColumns) == 0 {
    82  		return false, nil
    83  	}
    84  
    85  	spec := v.Specs[0]
    86  
    87  OUTER:
    88  	for _, newCol := range spec.NewColumns {
    89  		notNull := false
    90  		for _, opt := range newCol.Options {
    91  			if opt.Tp == ast.ColumnOptionDefaultValue {
    92  				continue OUTER
    93  			}
    94  			if opt.Tp == ast.ColumnOptionNotNull {
    95  				notNull = true
    96  			}
    97  		}
    98  		if notNull {
    99  			return true, nil
   100  		}
   101  	}
   102  
   103  	return false, nil
   104  }