Upload
badoo-development
View
5.496
Download
1
Embed Size (px)
Citation preview
reformпуть к лучшему ORM
Алексей Палажченко mc² software
Цели database/sqlsrc/database/sql/doc.txt
• generic database API for SQL/SQL-like, feel like Go
• common cases, portable, no quirks
• consistent but flexible type conversions
• concurrency, thread safety, built-in pool
• push complexity to drivers via optional interfaces
Интерфейс database/sql
• DB: Open, Close, Begin, Prepare, Driver
• DB, Stmt, Tx: Query, QueryRow, Exec
• Rows: Next, Scan, Err, Close
• Result: LastInsertId, RowsAffected
• NullBool, NullInt64, NullFloat64, NullString
• Scanner: Scan(src interface{}) error
INSERTresult, err := db.Exec( "INSERT INTO users (name) "+ "VALUES ($1)", "gopher" )
SELECTdefer rows.Close() for rows.Next() { var name string if e := rows.Scan(&name); e != nil { log.Fatal(e) } fmt.Println(name) } if e := rows.Err(); e != nil { log.Fatal(e) }
Интерфейс database/sql/driver
• Value: пустой интерфейс
• ValueConverter: ConvertValue(v interface{}) (Value, error)
• Valuer: Value() (Value, error)
database/sql/driver.Value• nil
• int64
• float64
• bool
• []byte (non-nil)
• string everywhere except from Rows.Next. #6497
• time.Time (боль с часовыми зонами)
Свои типыfunc (j JSONText) Value() (driver.Value, error) { if j == nil { return nil, nil }
var m json.RawMessage err := json.Unmarshal(j, &m) if err != nil { return []byte{}, err } return []byte(j), nil }
Свои типыfunc (j *JSONText) Scan(value interface{}) error { if value == nil { *j = nil return nil }
v, ok := value.([]byte) if !ok { return fmt.Errorf("error") }
*j = JSONText(append((*j)[0:0], v...)) return nil }
Драйвера• github.com/golang/go/wiki/SQLDrivers
• github.com/bradfitz/go-sql-test
Зачем ORM?
INSERTresult, err := db.Exec( "INSERT INTO users (name) "+ "VALUES ($1)", "gopher" )
SELECTdefer rows.Close() for rows.Next() { var name string if e := rows.Scan(&name); e != nil { log.Fatal(e) } fmt.Println(name) } if e := rows.Err(); e != nil { log.Fatal(e) }
ORM• Не-ORM / малые ORM (например, отображение
Scan строк в структуры)
• Большие ORM
ORM
func Save(m interface{}) error
ORM
Save(User{Name: "gopher"}) Save(&User{Name: "gopher"}) Save(nil) Save(42) Save("Batman!!")
Идея: struct для данных
type Person struct { ID int64 `sql:"id,omitempty"` Name string `sql:"name,omitempty"` }
Идея: непустые интерфейсы
type Record interface { Values() []interface{} Pointers() []interface{} PrimaryKeyPointer() interface{} SetPrimaryKey(id interface{}) Table() Table }
funс Save(record Record) error
Идея: генерация кода
• struct и код из XML
• XML из information_schema
• struct пишется, код генерируется из него
Проблемы: Go vs SQL• SQL: значения по-умолчанию
• SQL: отсутствие в запросе
• Go: zero value
person := &Person{ Name: "gopher", } if err := DB.Save(person); err != nil { log.Fatal(err) }
Что почитать• Документацию database/sql/…
• Код database/sql/…
• github.com/mc2soft/pq-types
• github.com/AlekSi/reform
• https://groups.google.com/forum/#!forum/golang-ru
• http://www.meetup.com/Golang-Moscow/
• http://4gophers.ru
• http://4gophers.ru/slack
• https://golangshow.com