// AsInterface converts the ValExpr to an interface. It converts // ValTuple to []interface{}, ValArg to string, StrVal to sqltypes.String, // NumVal to sqltypes.Numeric. Otherwise, it returns an error. func AsInterface(node ValExpr) (interface{}, error) { switch node := node.(type) { case ValTuple: vals := make([]interface{}, 0, len(node)) for _, val := range node { v, err := AsInterface(val) if err != nil { return nil, err } vals = append(vals, v) } return vals, nil case ValArg: return string(node), nil case StrVal: return sqltypes.MakeString(node), nil case NumVal: n, err := sqltypes.BuildNumeric(string(node)) if err != nil { return nil, fmt.Errorf("type mismatch: %s", err) } return n, nil } return nil, fmt.Errorf("unexpected node %v", node) }
// To do create business func (d *AlterDDL) Do() (interface{}, error) { d.Mut.Lock() defer d.Mut.Unlock() result, curTable, err := d.alterOnAllShard("alterddl") if err != nil { return nil, err } // parse the sql. cols := sqlparser.ParseAlterPart(d.Sql, d.TableName) for colName, options := range cols { alterAction, _ := strconv.Atoi(options["action_id"]) colExtra := "" if _, isOk := options["auto_increment"]; isOk { colExtra = "auto_increment" } switch alterAction { case sqlparser.ADD_ALTER: curTable.AddColumn(colName, options["type"], sqltypes.MakeString([]byte("")), colExtra) case sqlparser.DROP_ALTER: curTable.RemoveColumn(colName) case sqlparser.CHANGE_ALTER: curTable.ChangeColumn(colName, options) } } return result, nil }
func TestStarParam(t *testing.T) { buf := NewTrackedBuffer(nil) buf.Myprintf("select * from a where id in (%a)", "*") pq := buf.ParsedQuery() listvars := []sqltypes.Value{ sqltypes.MakeNumeric([]byte("1")), sqltypes.MakeString([]byte("aa")), } bytes, err := pq.GenerateQuery(nil, listvars) if err != nil { t.Errorf("generate failed: %v", err) return } got := string(bytes) want := "select * from a where id in (1, 'aa')" if got != want { t.Errorf("got %s, want %s", got, want) } }
// to restore the table column to memery. // func (ta *MysqlTable) RestoreColumnsByDB() error { shardTabOrderId := 0 db, err := ta.GetSlaveShardDBConn(shardTabOrderId) if err != nil { return err } shardTblN := ta.Shards[shardTabOrderId].Name // var rows *sql.Rows rows, err := db.Query(fmt.Sprintf("desc `%s`", shardTblN)) if err != nil { return err } if rows != nil { for rows.Next() { var colName string var colType string var colNull string var colKey []byte var colDefault []byte var colExtra string err = rows.Scan(&colName, &colType, &colNull, &colKey, &colDefault, &colExtra) if err != nil { return err } // if colNull=="" || string(colKey)=="" {} ta.AddColumn(colName, colType, sqltypes.MakeString(colDefault), colExtra) } rows.Close() } return nil }
func (ta *MysqlTable) AddColumn(name string, columnType string, defval sqltypes.Value, extra string) { index := len(ta.Columns) ta.Columns = append(ta.Columns, TableColumn{Name: name}) if strings.Contains(columnType, "int") { ta.Columns[index].Category = CAT_NUMBER } else if strings.HasPrefix(columnType, "varbinary") { ta.Columns[index].Category = CAT_VARBINARY } else { ta.Columns[index].Category = CAT_OTHER } if extra == "auto_increment" { ta.Columns[index].IsAuto = true // Ignore default value, if any return } if defval.IsNull() { return } if ta.Columns[index].Category == CAT_NUMBER { ta.Columns[index].Default = sqltypes.MakeNumeric(defval.Raw()) } else { ta.Columns[index].Default = sqltypes.MakeString(defval.Raw()) } }
func (node StrVal) Format(buf *TrackedBuffer) { s := sqltypes.MakeString([]byte(node)) s.EncodeSql(buf) }
func TestParsedQuery(t *testing.T) { tcases := []struct { desc string query string bindVars map[string]interface{} listVars []sqltypes.Value output string }{ { "no subs", "select * from a where id = 2", map[string]interface{}{ "id": 1, }, nil, "select * from a where id = 2", }, { "simple bindvar sub", "select * from a where id1 = :id1 and id2 = :id2", map[string]interface{}{ "id1": 1, "id2": nil, }, nil, "select * from a where id1 = 1 and id2 = null", }, { "missing bind var", "select * from a where id1 = :id1 and id2 = :id2", map[string]interface{}{ "id1": 1, }, nil, "missing bind var id2", }, { "unencodable bind var", "select * from a where id1 = :id", map[string]interface{}{ "id": make([]int, 1), }, nil, "unsupported bind variable type []int: [0]", }, { "list var sub", "select * from a where id = :0 and name = :1", nil, []sqltypes.Value{ sqltypes.MakeNumeric([]byte("1")), sqltypes.MakeString([]byte("aa")), }, "select * from a where id = 1 and name = 'aa'", }, { "list inside bind vars", "select * from a where id in (:vals)", map[string]interface{}{ "vals": []sqltypes.Value{ sqltypes.MakeNumeric([]byte("1")), sqltypes.MakeString([]byte("aa")), }, }, nil, "select * from a where id in (1, 'aa')", }, { "two lists inside bind vars", "select * from a where id in (:vals)", map[string]interface{}{ "vals": [][]sqltypes.Value{ []sqltypes.Value{ sqltypes.MakeNumeric([]byte("1")), sqltypes.MakeString([]byte("aa")), }, []sqltypes.Value{ sqltypes.Value{}, sqltypes.MakeString([]byte("bb")), }, }, }, nil, "select * from a where id in ((1, 'aa'), (null, 'bb'))", }, { "illega list var name", "select * from a where id = :0a", nil, []sqltypes.Value{ sqltypes.MakeNumeric([]byte("1")), sqltypes.MakeString([]byte("aa")), }, `unexpected: strconv.ParseInt: parsing "0a": invalid syntax for 0a`, }, { "out of range list var index", "select * from a where id = :10", nil, []sqltypes.Value{ sqltypes.MakeNumeric([]byte("1")), sqltypes.MakeString([]byte("aa")), }, "index out of range: 10", }, } for _, tcase := range tcases { tree, err := Parse(tcase.query) if err != nil { t.Errorf("parse failed for %s: %v", tcase.desc, err) continue } buf := NewTrackedBuffer(nil) buf.Myprintf("%v", tree) pq := buf.ParsedQuery() bytes, err := pq.GenerateQuery(tcase.bindVars, tcase.listVars) var got string if err != nil { got = err.Error() } else { got = string(bytes) } if got != tcase.output { t.Errorf("for test case: %s, got: '%s', want '%s'", tcase.desc, got, tcase.output) } } }