// Package mysql wraps the github.com/go-sql-driver/mysql MySQL driver. See // https://github.com/upper/db/adapter/mysql for documentation, particularities and usage // examples. package mysql import ( "reflect" "strings" "database/sql" "git.hexq.cn/tiglog/mydb" "git.hexq.cn/tiglog/mydb/internal/sqladapter" "git.hexq.cn/tiglog/mydb/internal/sqladapter/exql" _ "github.com/go-sql-driver/mysql" // MySQL driver. ) // database is the actual implementation of Database type database struct { } func (*database) Template() *exql.Template { return template } func (*database) OpenDSN(sess sqladapter.Session, dsn string) (*sql.DB, error) { return sql.Open("mysql", dsn) } func (*database) Collections(sess sqladapter.Session) (collections []string, err error) { q := sess.SQL(). Select("table_name"). From("information_schema.tables"). Where("table_schema = ?", sess.Name()) iter := q.Iterator() defer iter.Close() for iter.Next() { var tableName string if err := iter.Scan(&tableName); err != nil { return nil, err } collections = append(collections, tableName) } if err := iter.Err(); err != nil { return nil, err } return collections, nil } func (d *database) ConvertValue(in interface{}) interface{} { switch v := in.(type) { case *map[string]interface{}: return (*JSONMap)(v) case map[string]interface{}: return (*JSONMap)(&v) } dv := reflect.ValueOf(in) if dv.IsValid() { if dv.Type().Kind() == reflect.Ptr { dv = dv.Elem() } switch dv.Kind() { case reflect.Map: if reflect.TypeOf(in).Kind() == reflect.Ptr { w := reflect.ValueOf(in) z := reflect.New(w.Elem().Type()) w.Elem().Set(z.Elem()) } return &JSON{in} case reflect.Slice: return &JSON{in} } } return in } func (*database) Err(err error) error { if err != nil { // This error is not exported so we have to check it by its string value. s := err.Error() if strings.Contains(s, `many connections`) { return mydb.ErrTooManyClients } } return err } func (*database) NewCollection() sqladapter.CollectionAdapter { return &collectionAdapter{} } func (*database) LookupName(sess sqladapter.Session) (string, error) { q := sess.SQL(). Select(mydb.Raw("DATABASE() AS name")) iter := q.Iterator() defer iter.Close() if iter.Next() { var name string if err := iter.Scan(&name); err != nil { return "", err } return name, nil } return "", iter.Err() } func (*database) TableExists(sess sqladapter.Session, name string) error { q := sess.SQL(). Select("table_name"). From("information_schema.tables"). Where("table_schema = ? AND table_name = ?", sess.Name(), name) iter := q.Iterator() defer iter.Close() if iter.Next() { var name string if err := iter.Scan(&name); err != nil { return err } return nil } if err := iter.Err(); err != nil { return err } return mydb.ErrCollectionDoesNotExist } func (*database) PrimaryKeys(sess sqladapter.Session, tableName string) ([]string, error) { q := sess.SQL(). Select("k.column_name"). From("information_schema.key_column_usage AS k"). Where(` k.constraint_name = 'PRIMARY' AND k.table_schema = ? AND k.table_name = ? `, sess.Name(), tableName). OrderBy("k.ordinal_position") iter := q.Iterator() defer iter.Close() pk := []string{} for iter.Next() { var k string if err := iter.Scan(&k); err != nil { return nil, err } pk = append(pk, k) } if err := iter.Err(); err != nil { return nil, err } return pk, nil }