Permalink
Browse files

goの初期実装を他のLLの実装と揃えるためにsingleであっても全県fetchさせる

  • Loading branch information...
ken39arg committed Oct 16, 2018
1 parent 667252d commit 4d1f0c04f5f7e7fbb7337ab072a6e7a73ccc5e1d

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -19,13 +19,8 @@ var (
ErrNoOrderForTrade = errors.New("no order for trade")
)
type RowScanner interface {
Scan(...interface{}) error
}
type QueryExecutor interface {
Exec(string, ...interface{}) (sql.Result, error)
QueryRow(string, ...interface{}) *sql.Row
Query(string, ...interface{}) (*sql.Rows, error)
}
@@ -5,7 +5,6 @@ import (
"isucon8/isubank"
"time"
"github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
)
@@ -14,6 +13,7 @@ const (
OrderTypeSell = "sell"
)
//go:generate scanner
type Order struct {
ID int64 `json:"id"`
Type string `json:"type"`
@@ -27,48 +27,12 @@ type Order struct {
Trade *Trade `json:"trade,omitempty"`
}
func scanOrder(r RowScanner) (*Order, error) {
var v Order
var closedAt mysql.NullTime
var tradeID sql.NullInt64
if err := r.Scan(&v.ID, &v.Type, &v.UserID, &v.Amount, &v.Price, &closedAt, &tradeID, &v.CreatedAt); err != nil {
return nil, err
}
if closedAt.Valid {
v.ClosedAt = &closedAt.Time
}
if tradeID.Valid {
v.TradeID = tradeID.Int64
}
return &v, nil
}
func queryOrders(d QueryExecutor, query string, args ...interface{}) ([]*Order, error) {
rows, err := d.Query(query, args...)
if err != nil {
return nil, errors.Wrapf(err, "Query failed. query:%s, args:% v", query, args)
}
defer rows.Close()
orders := []*Order{}
for rows.Next() {
order, err := scanOrder(rows)
if err != nil {
return nil, errors.Wrapf(err, "Scan failed.")
}
orders = append(orders, order)
}
if err = rows.Err(); err != nil {
return nil, errors.Wrapf(err, "rows.Err failed.")
}
return orders, nil
}
func GetOrdersByUserID(d QueryExecutor, userID int64) ([]*Order, error) {
return queryOrders(d, "SELECT * FROM orders WHERE user_id = ? AND (closed_at IS NULL OR trade_id IS NOT NULL) ORDER BY created_at ASC", userID)
return scanOrders(d.Query("SELECT * FROM orders WHERE user_id = ? AND (closed_at IS NULL OR trade_id IS NOT NULL) ORDER BY created_at ASC", userID))
}
func GetOrdersByUserIDAndLastTradeId(d QueryExecutor, userID int64, tradeID int64) ([]*Order, error) {
return queryOrders(d, `SELECT * FROM orders WHERE user_id = ? AND trade_id IS NOT NULL AND trade_id > ? ORDER BY created_at ASC`, userID, tradeID)
return scanOrders(d.Query(`SELECT * FROM orders WHERE user_id = ? AND trade_id IS NOT NULL AND trade_id > ? ORDER BY created_at ASC`, userID, tradeID))
}
func getOpenOrderByID(tx *sql.Tx, id int64) (*Order, error) {
@@ -87,19 +51,19 @@ func getOpenOrderByID(tx *sql.Tx, id int64) (*Order, error) {
}
func GetOrderByID(d QueryExecutor, id int64) (*Order, error) {
return scanOrder(d.QueryRow("SELECT * FROM orders WHERE id = ?", id))
return scanOrder(d.Query("SELECT * FROM orders WHERE id = ?", id))
}
func getOrderByIDWithLock(tx *sql.Tx, id int64) (*Order, error) {
return scanOrder(tx.QueryRow("SELECT * FROM orders WHERE id = ? FOR UPDATE", id))
return scanOrder(tx.Query("SELECT * FROM orders WHERE id = ? FOR UPDATE", id))
}
func GetLowestSellOrder(d QueryExecutor) (*Order, error) {
return scanOrder(d.QueryRow("SELECT * FROM orders WHERE type = ? AND closed_at IS NULL ORDER BY price ASC, created_at ASC LIMIT 1", OrderTypeSell))
return scanOrder(d.Query("SELECT * FROM orders WHERE type = ? AND closed_at IS NULL ORDER BY price ASC, created_at ASC LIMIT 1", OrderTypeSell))
}
func GetHighestBuyOrder(d QueryExecutor) (*Order, error) {
return scanOrder(d.QueryRow("SELECT * FROM orders WHERE type = ? AND closed_at IS NULL ORDER BY price DESC, created_at ASC LIMIT 1", OrderTypeBuy))
return scanOrder(d.Query("SELECT * FROM orders WHERE type = ? AND closed_at IS NULL ORDER BY price DESC, created_at ASC LIMIT 1", OrderTypeBuy))
}
func FetchOrderRelation(d QueryExecutor, order *Order) error {
@@ -0,0 +1,165 @@
package model
import (
"database/sql"
"github.com/go-sql-driver/mysql"
)
func scanCandlestickDatas(rows *sql.Rows, e error) (candlestickDatas []*CandlestickData, err error) {
if e != nil {
return nil, e
}
defer func() {
err = rows.Close()
}()
candlestickDatas = []*CandlestickData{}
for rows.Next() {
var v CandlestickData
if err = rows.Scan(&v.Time, &v.Open, &v.Close, &v.High, &v.Low); err != nil {
return
}
candlestickDatas = append(candlestickDatas, &v)
}
err = rows.Err()
return
}
func scanCandlestickData(rows *sql.Rows, err error) (*CandlestickData, error) {
v, err := scanCandlestickDatas(rows, err)
if err != nil {
return nil, err
}
if len(v) > 0 {
return v[0], nil
}
return nil, sql.ErrNoRows
}
func scanOrders(rows *sql.Rows, e error) (orders []*Order, err error) {
if e != nil {
return nil, e
}
defer func() {
err = rows.Close()
}()
orders = []*Order{}
for rows.Next() {
var v Order
var closedAt mysql.NullTime
var tradeID sql.NullInt64
if err = rows.Scan(&v.ID, &v.Type, &v.UserID, &v.Amount, &v.Price, &closedAt, &tradeID, &v.CreatedAt); err != nil {
return nil, err
}
if closedAt.Valid {
v.ClosedAt = &closedAt.Time
}
if tradeID.Valid {
v.TradeID = tradeID.Int64
}
orders = append(orders, &v)
}
err = rows.Err()
return
}
func scanOrder(rows *sql.Rows, err error) (*Order, error) {
v, err := scanOrders(rows, err)
if err != nil {
return nil, err
}
if len(v) > 0 {
return v[0], nil
}
return nil, sql.ErrNoRows
}
func scanSettings(rows *sql.Rows, e error) (settings []*Setting, err error) {
if e != nil {
return nil, e
}
defer func() {
err = rows.Close()
}()
settings = []*Setting{}
for rows.Next() {
var v Setting
if err = rows.Scan(&v.Name, &v.Val); err != nil {
return
}
settings = append(settings, &v)
}
err = rows.Err()
return
}
func scanSetting(rows *sql.Rows, err error) (*Setting, error) {
v, err := scanSettings(rows, err)
if err != nil {
return nil, err
}
if len(v) > 0 {
return v[0], nil
}
return nil, sql.ErrNoRows
}
func scanTrades(rows *sql.Rows, e error) (trades []*Trade, err error) {
if e != nil {
return nil, e
}
defer func() {
err = rows.Close()
}()
trades = []*Trade{}
for rows.Next() {
var v Trade
if err = rows.Scan(&v.ID, &v.Amount, &v.Price, &v.CreatedAt); err != nil {
return
}
trades = append(trades, &v)
}
err = rows.Err()
return
}
func scanTrade(rows *sql.Rows, err error) (*Trade, error) {
v, err := scanTrades(rows, err)
if err != nil {
return nil, err
}
if len(v) > 0 {
return v[0], nil
}
return nil, sql.ErrNoRows
}
func scanUsers(rows *sql.Rows, e error) (users []*User, err error) {
if e != nil {
return nil, e
}
defer func() {
err = rows.Close()
}()
users = []*User{}
for rows.Next() {
var v User
if err = rows.Scan(&v.ID, &v.BankID, &v.Name, &v.Password, &v.CreatedAt); err != nil {
return
}
users = append(users, &v)
}
err = rows.Err()
return
}
func scanUser(rows *sql.Rows, err error) (*User, error) {
v, err := scanUsers(rows, err)
if err != nil {
return nil, err
}
if len(v) > 0 {
return v[0], nil
}
return nil, sql.ErrNoRows
}
@@ -15,14 +15,23 @@ const (
LogAppid = "log_appid"
)
//go:generate scanner
type Setting struct {
Name string
Val string
}
func SetSetting(d QueryExecutor, k, v string) error {
_, err := d.Exec(`INSERT INTO setting (name, val) VALUES (?, ?) ON DUPLICATE KEY UPDATE val = VALUES(val)`, k, v)
return err
}
func GetSetting(d QueryExecutor, k string) (v string, err error) {
err = d.QueryRow(`SELECT val FROM setting WHERE name = ?`, k).Scan(&v)
return
func GetSetting(d QueryExecutor, k string) (string, error) {
s, err := scanSetting(d.Query(`SELECT val FROM setting WHERE name = ?`, k))
if err != nil {
return "", err
}
return s.Val, nil
}
func Isubank(d QueryExecutor) (*isubank.Isubank, error) {
@@ -10,13 +10,15 @@ import (
"github.com/pkg/errors"
)
//go:generate scanner
type Trade struct {
ID int64 `json:"id"`
Amount int64 `json:"amount"`
Price int64 `json:"price"`
CreatedAt time.Time `json:"created_at"`
}
//go:generate scanner
type CandlestickData struct {
Time time.Time `json:"time"`
Open int64 `json:"open"`
@@ -25,23 +27,15 @@ type CandlestickData struct {
Low int64 `json:"low"`
}
func scanTrade(r RowScanner) (*Trade, error) {
var v Trade
if err := r.Scan(&v.ID, &v.Amount, &v.Price, &v.CreatedAt); err != nil {
return nil, err
}
return &v, nil
}
func GetTradeByID(d QueryExecutor, id int64) (*Trade, error) {
return scanTrade(d.QueryRow("SELECT * FROM trade WHERE id = ?", id))
return scanTrade(d.Query("SELECT * FROM trade WHERE id = ?", id))
}
func GetLatestTrade(d QueryExecutor) (*Trade, error) {
return scanTrade(d.QueryRow("SELECT * FROM trade ORDER BY id DESC"))
return scanTrade(d.Query("SELECT * FROM trade ORDER BY id DESC"))
}
func GetCandlestickData(d QueryExecutor, mt time.Time, tf string) ([]CandlestickData, error) {
func GetCandlestickData(d QueryExecutor, mt time.Time, tf string) ([]*CandlestickData, error) {
query := fmt.Sprintf(`
SELECT m.t, a.price, b.price, m.h, m.l
FROM (
@@ -59,23 +53,7 @@ func GetCandlestickData(d QueryExecutor, mt time.Time, tf string) ([]Candlestick
JOIN trade b ON b.id = m.max_id
ORDER BY m.t
`, tf, "%Y-%m-%d %H:%i:%s")
rows, err := d.Query(query, mt)
if err != nil {
return nil, errors.Wrapf(err, "Query failed. query:%s, starttime:%s", query, mt)
}
defer rows.Close()
datas := []CandlestickData{}
for rows.Next() {
var cd CandlestickData
if err = rows.Scan(&cd.Time, &cd.Open, &cd.Close, &cd.High, &cd.Low); err != nil {
return nil, errors.Wrapf(err, "Scan failed.")
}
datas = append(datas, cd)
}
if err = rows.Err(); err != nil {
return nil, errors.Wrapf(err, "rows.Err failed.")
}
return datas, nil
return scanCandlestickDatas(d.Query(query, mt))
}
func HasTradeChanceByOrder(d QueryExecutor, orderID int64) (bool, error) {
@@ -212,9 +190,9 @@ func tryTrade(tx *sql.Tx, orderID int64) error {
var targetOrders []*Order
switch order.Type {
case OrderTypeBuy:
targetOrders, err = queryOrders(tx, `SELECT * FROM orders WHERE type = ? AND closed_at IS NULL AND price <= ? ORDER BY price ASC, created_at ASC, id ASC`, OrderTypeSell, order.Price)
targetOrders, err = scanOrders(tx.Query(`SELECT * FROM orders WHERE type = ? AND closed_at IS NULL AND price <= ? ORDER BY price ASC, created_at ASC, id ASC`, OrderTypeSell, order.Price))
case OrderTypeSell:
targetOrders, err = queryOrders(tx, `SELECT * FROM orders WHERE type = ? AND closed_at IS NULL AND price >= ? ORDER BY price DESC, created_at ASC, id ASC`, OrderTypeBuy, order.Price)
targetOrders, err = scanOrders(tx.Query(`SELECT * FROM orders WHERE type = ? AND closed_at IS NULL AND price >= ? ORDER BY price DESC, created_at ASC, id ASC`, OrderTypeBuy, order.Price))
}
if err != nil {
return errors.Wrap(err, "find target orders")
Oops, something went wrong.

0 comments on commit 4d1f0c0

Please sign in to comment.