// AsInterface converts the ValExpr to an interface. It converts // ValTuple to []interface{}, ValArg to string, StrVal to sqltypes.String, // NumVal to sqltypes.Numeric, NullVal to nil. // 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 hack.String(node), nil case ListArg: return hack.String(node), nil case StrVal: return sqltypes.MakeString(node), nil case NumVal: n, err := sqltypes.BuildNumeric(hack.String(node)) if err != nil { return nil, fmt.Errorf("type mismatch: %s", err) } return n, nil case *NullVal: return nil, nil } return nil, fmt.Errorf("unexpected node %v", node) }
func (c *Conn) dispatch(data []byte) error { cmd := data[0] data = data[1:] log.Debug(c.connectionId, cmd, hack.String(data)) c.lastCmd = hack.String(data) token := c.server.GetToken() c.server.GetRWlock().RLock() defer func() { c.server.GetRWlock().RUnlock() c.server.ReleaseToken(token) }() c.server.IncCounter(mysql.MYSQL_COMMAND(cmd).String()) switch mysql.MYSQL_COMMAND(cmd) { case mysql.COM_QUIT: c.Close() return nil case mysql.COM_QUERY: return c.handleQuery(hack.String(data)) case mysql.COM_PING: return c.writeOkFlush(nil) case mysql.COM_INIT_DB: log.Debug(cmd, hack.String(data)) if err := c.useDB(hack.String(data)); err != nil { return errors.Trace(err) } return c.writeOkFlush(nil) case mysql.COM_FIELD_LIST: return c.handleFieldList(data) case mysql.COM_STMT_PREPARE: // not support server side prepare yet case mysql.COM_STMT_EXECUTE: log.Fatal("not support", data) case mysql.COM_STMT_CLOSE: return c.handleStmtClose(data) case mysql.COM_STMT_SEND_LONG_DATA: log.Fatal("not support", data) case mysql.COM_STMT_RESET: log.Fatal("not support", data) default: msg := fmt.Sprintf("command %d not supported now", cmd) return mysql.NewError(mysql.ER_UNKNOWN_ERROR, msg) } return nil }
func getPKValues(conditions []sqlparser.BoolExpr, pkIndex *schema.Index) (pkValues []interface{}, err error) { pkIndexScore := NewIndexScore(pkIndex) pkValues = make([]interface{}, len(pkIndexScore.ColumnMatch)) for _, condition := range conditions { condition, ok := condition.(*sqlparser.ComparisonExpr) if !ok { return nil, nil } if !sqlparser.StringIn(condition.Operator, sqlparser.AST_EQ, sqlparser.AST_IN) { return nil, nil } index := pkIndexScore.FindMatch(hack.String(condition.Left.(*sqlparser.ColName).Name)) if index == -1 { return nil, nil } switch condition.Operator { case sqlparser.AST_EQ, sqlparser.AST_IN: var err error pkValues[index], err = sqlparser.AsInterface(condition.Right) if err != nil { return nil, err } default: panic("unreachable") } } if pkIndexScore.GetScore() == PERFECT_SCORE { return pkValues, nil } return nil, nil }
func (c *MySqlConn) readResultColumns(result *Result) (err error) { var i int var data []byte for { data, err = c.readPacket() if err != nil { return } // EOF Packet if c.isEOFPacket(data) { if c.capability&CLIENT_PROTOCOL_41 > 0 { //result.Warnings = binary.LittleEndian.Uint16(data[1:]) //todo add strict_mode, warning will be treat as error result.Status = binary.LittleEndian.Uint16(data[3:]) c.status = result.Status } if i != len(result.Fields) { err = ErrMalformPacket } return } result.Fields[i], err = FieldData(data).Parse() if err != nil { return } result.FieldNames[hack.String(result.Fields[i].Name)] = i i++ } }
func (tkn *Tokenizer) scanIdentifier() (int, []byte) { buffer := bytes.NewBuffer(tkn.alloc.AllocBytes(128)) buffer.WriteByte(byte(tkn.lastChar)) for tkn.next(); isLetter(tkn.lastChar) || isDigit(tkn.lastChar); tkn.next() { buffer.WriteByte(byte(tkn.lastChar)) } if keywordId, found := keywords[hack.String(buffer.Bytes())]; found { return keywordId, buffer.Bytes() } return ID, buffer.Bytes() }
// GetTableName returns the table name from the SimpleTableExpr // only if it's a simple expression. Otherwise, it returns "". func GetTableName(node SimpleTableExpr) string { n, ok := node.(*TableName) if ok { if len(n.Qualifier) > 0 { return string(n.Qualifier) + "." + string(n.Name) } else { return hack.String(n.Name) } } // sub-select or '.' expression return "" }
func (c *Conn) limitSelectResult(r *mysql.Resultset, stmt *sqlparser.Select) error { if stmt.Limit == nil { return nil } var offset, count int64 var err error if stmt.Limit.Offset == nil { offset = 0 } else { if o, ok := stmt.Limit.Offset.(sqlparser.NumVal); !ok { return errors.Errorf("invalid select limit %s", nstring(stmt.Limit, c.alloc)) } else { if offset, err = strconv.ParseInt(hack.String([]byte(o)), 10, 64); err != nil { return errors.Trace(err) } } } if o, ok := stmt.Limit.Rowcount.(sqlparser.NumVal); !ok { return errors.Errorf("invalid limit %s", nstring(stmt.Limit, c.alloc)) } else { if count, err = strconv.ParseInt(hack.String([]byte(o)), 10, 64); err != nil { return errors.Trace(err) } else if count < 0 { return errors.Errorf("invalid limit %s", nstring(stmt.Limit, c.alloc)) } } if offset+count > int64(len(r.Values)) { count = int64(len(r.Values)) - offset } r.Values = r.Values[offset : offset+count] r.RowDatas = r.RowDatas[offset : offset+count] return nil }
func EncodeValue(value interface{}) string { switch val := value.(type) { case int: return Uint64Key(val).String() case uint64: return Uint64Key(val).String() case int64: return Uint64Key(val).String() case string: return val case []byte: return hack.String(val) } panic(NewKeyError("Unexpected key variable type %T", value)) }
func (c *Conn) handleFieldList(data []byte) error { index := bytes.IndexByte(data, 0x00) table := hack.String(data[0:index]) wildcard := hack.String(data[index+1:]) shardIds, err := c.getShardIds(table) if err != nil { return err } //todo: pass through if len(shardIds) == 0 { return errors.Errorf("no rule for table %s, %+v, please check config file", table, c.schema) } //hard code, assume all of the shard has the same schema n := c.server.GetShard(shardIds[0]) if n == nil { return errors.Errorf("shard %s not found, %+v", shardIds, c.schema) } co, err := n.getMasterConn() if err != nil { return errors.Trace(err) } defer co.Close() if err = co.UseDB(c.db); err != nil { return errors.Trace(err) } if fs, err := co.FieldList(table, wildcard); err != nil { return errors.Trace(err) } else { return errors.Trace(c.writeFieldList(c.status, fs)) } }
func NumValue(value interface{}) int64 { switch val := value.(type) { case int: return int64(val) case uint64: return int64(val) case int64: return int64(val) case string: if v, err := strconv.ParseInt(val, 10, 64); err != nil { panic(NewKeyError("invalid num format %s", v)) } else { return v } case []byte: if v, err := strconv.ParseInt(hack.String(val), 10, 64); err != nil { panic(NewKeyError("invalid num format %s", v)) } else { return v } } panic(NewKeyError("Unexpected key variable type %T", value)) }
func (r *Resultset) GetString(row, column int) (string, error) { d, err := r.GetValue(row, column) if err != nil { return "", err } switch v := d.(type) { case string: return v, nil case []byte: return hack.String(v), nil case int64: return strconv.FormatInt(v, 10), nil case uint64: return strconv.FormatUint(v, 10), nil case float64: return strconv.FormatFloat(v, 'f', -1, 64), nil case nil: return "", nil default: return "", fmt.Errorf("data type is %T", v) } }
func (buf *TrackedBuffer) ParsedQuery() *ParsedQuery { return &ParsedQuery{Query: hack.String(buf.Bytes()), bindLocations: buf.bindLocations} }
// String returns the raw value as a string func (v Value) String() string { if v.Inner == nil { return "" } return hack.String(v.Inner.raw()) }
// GetColName returns the column name, only if // it's a simple expression. Otherwise, it returns "". func GetColName(node Expr) string { if n, ok := node.(*ColName); ok { return hack.String(bytes.ToLower(n.Name)) } return "" }