func (ao *SQLAuctionOrderbook) GetOrder(orderID *match.OrderID) (aucOrder *match.AuctionOrderIDPair, err error) {
	aucOrder = new(match.AuctionOrderIDPair)
	aucOrder.Order = new(match.AuctionOrder)
	var tx *sql.Tx
	if tx, err = ao.DBHandler.Begin(); err != nil {
		err = fmt.Errorf("Error when beginning transaction for GetOrder: %s", err)
		return
	}
	defer func() {
		if err != nil {
			tx.Rollback()
			err = fmt.Errorf("Error with GetOrder: \n%s", err)
			return
		}
		err = tx.Commit()
	}()
	if _, err = tx.Exec("USE " + ao.auctionOrderSchema + ";"); err != nil {
		err = fmt.Errorf("Error using auction schema for GetOrder: %s", err)
		return
	}
	var row *sql.Row
	selectOrderQuery := fmt.Sprintf("SELECT pubkey, side, price, amountHave, amountWant, auctionID, nonce, sig, hashedOrder FROM %s WHERE hashedOrder='%x';", ao.pair, orderID)
	row = tx.QueryRow(selectOrderQuery)
	var pkBytes []byte
	var auctionIDBytes []byte
	var nonceBytes []byte
	var sigBytes []byte
	var hashedOrderBytes []byte
	if err = row.Scan(&pkBytes, &aucOrder.Order.Side, &aucOrder.Price, &aucOrder.Order.AmountHave, &aucOrder.Order.AmountWant, &auctionIDBytes, &nonceBytes, &sigBytes, &hashedOrderBytes); err != nil {
		err = fmt.Errorf("Error scanning into order for GetOrdersForPubkey: %s", err)
		return
	}
	for _, byteArrayPtr := range []*[]byte{&pkBytes, &auctionIDBytes, &nonceBytes, &sigBytes} {
		if *byteArrayPtr, err = hex.DecodeString(string(*byteArrayPtr)); err != nil {
			err = fmt.Errorf("Error decoding bytes for GetOrdersForPubkey: %s", err)
			return
		}
	}
	if err = aucOrder.OrderID.UnmarshalText(hashedOrderBytes); err != nil {
		err = fmt.Errorf("Error unmarshalling order ID for GetOrdersForPubkey: %s", err)
		return
	}
	copy(aucOrder.Order.Pubkey[:], pkBytes)
	copy(aucOrder.Order.AuctionID[:], auctionIDBytes)
	copy(aucOrder.Order.Signature[:], sigBytes)
	copy(aucOrder.Order.Nonce[:], nonceBytes)
	aucOrder.Order.TradingPair = *ao.pair
	return
}
GetOrder gets an order from an OrderID
package cxdbsql
import (
	"database/sql"
	"encoding/hex"
	"fmt"
	"net"
	"github.com/mit-dci/lit/crypto/koblitz"
	"github.com/mit-dci/opencx/logging"
	"github.com/mit-dci/opencx/match"
)
type SQLAuctionOrderbook struct {
	DBHandler *sql.DB
	dbUsername string
	dbPassword string
	dbAddr net.Addr
	auctionOrderSchema string
	pair *match.Pair
}
const (
	auctionOrderbookSchema = "pubkey VARBINARY(66), side TEXT, price DOUBLE(30, 2) UNSIGNED, amountHave BIGINT(64), amountWant BIGINT(64), auctionID VARBINARY(64), nonce VARBINARY(4), sig BLOB, hashedOrder VARBINARY(64), PRIMARY KEY (hashedOrder)"
)
func CreateAuctionOrderbook(pair *match.Pair) (book match.AuctionOrderbook, err error) {
	conf := new(dbsqlConfig)
	*conf = *defaultConf
	dbConfigSetup(conf)
	var addr net.Addr
	if addr, err = net.ResolveTCPAddr("tcp", net.JoinHostPort(conf.DBHost, fmt.Sprintf("%d", conf.DBPort))); err != nil {
		err = fmt.Errorf("Couldn't resolve db address for CreateAuctionEngine: %s", err)
		return
	}
	ao := &SQLAuctionOrderbook{
		dbUsername:         conf.DBUsername,
		dbPassword:         conf.DBPassword,
		auctionOrderSchema: conf.ReadOnlyAuctionSchemaName,
		dbAddr:             addr,
		pair:               pair,
	}
	if err = ao.setupAuctionOrderbookTables(); err != nil {
		err = fmt.Errorf("Error setting up auction orderbook tables while creating engine: %s", err)
		return
	}
	openString := fmt.Sprintf("%s:%s@%s(%s)/", ao.dbUsername, ao.dbPassword, ao.dbAddr.Network(), ao.dbAddr.String())
	if ao.DBHandler, err = sql.Open("mysql", openString); err != nil {
		err = fmt.Errorf("Error opening database for CreateAuctionEngine: %s", err)
		return
	}
	if err = ao.DBHandler.Ping(); err != nil {
		err = fmt.Errorf("Could not ping the database, is it running: %s", err)
		return
	}
	book = ao
	return
}
func (ao *SQLAuctionOrderbook) setupAuctionOrderbookTables() (err error) {
	openString := fmt.Sprintf("%s:%s@%s(%s)/", ao.dbUsername, ao.dbPassword, ao.dbAddr.Network(), ao.dbAddr.String())
	var rootHandler *sql.DB
	if rootHandler, err = sql.Open("mysql", openString); err != nil {
		err = fmt.Errorf("Error opening database for setup auction orderbook tables: %s", err)
		return
	}
	defer rootHandler.Close()
	if err = rootHandler.Ping(); err != nil {
		err = fmt.Errorf("Could not ping the database, is it running: %s", err)
		return
	}
	var tx *sql.Tx
	if tx, err = rootHandler.Begin(); err != nil {
		err = fmt.Errorf("Error when beginning transaction for setup auction orderbook tables: %s", err)
		return
	}
	defer func() {
		if err != nil {
			tx.Rollback()
			err = fmt.Errorf("Error while setting up auction orderbook tables: \n%s", err)
			return
		}
		err = tx.Commit()
	}()
	if _, err = tx.Exec("CREATE SCHEMA IF NOT EXISTS " + ao.auctionOrderSchema + ";"); err != nil {
		err = fmt.Errorf("Error creating schema for setup auction order tables: %s", err)
		return
	}
	if _, err = tx.Exec("USE " + ao.auctionOrderSchema + ";"); err != nil {
		err = fmt.Errorf("Could not use %s schema: %s", ao.auctionOrderSchema, err)
		return
	}
	createTableQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s);", ao.pair.String(), auctionEngineSchema)
	if _, err = tx.Exec(createTableQuery); err != nil {
		err = fmt.Errorf("Error creating auction orderbook table: %s", err)
		return
	}
	return
}
func (ao *SQLAuctionOrderbook) UpdateBookExec(exec *match.OrderExecution) (err error) {
	var tx *sql.Tx
	if tx, err = ao.DBHandler.Begin(); err != nil {
		err = fmt.Errorf("Error when beginning transaction for setup auction orderbook tables: %s", err)
		return
	}
	defer func() {
		if err != nil {
			tx.Rollback()
			err = fmt.Errorf("Error while setting up auction orderbook tables: \n%s", err)
			return
		}
		err = tx.Commit()
	}()
	if _, err = tx.Exec("USE " + ao.auctionOrderSchema + ";"); err != nil {
		err = fmt.Errorf("Error using auction schema to process order execution: %s", err)
		return
	}
	if exec.Filled {
		deleteOrderQuery := fmt.Sprintf("DELETE FROM %s WHERE hashedOrder='%x';", ao.pair.String(), exec.OrderID)
		var res sql.Result
		if res, err = tx.Exec(deleteOrderQuery); err != nil {
			err = fmt.Errorf("Error deleting order within tx for processorderexecution: %s", err)
			return
		}
		var rowsAffected int64
		if rowsAffected, err = res.RowsAffected(); err != nil {
			err = fmt.Errorf("Error while getting rows affected for process order execution: %s", err)
			return
		}
		if rowsAffected != 1 {
			err = fmt.Errorf("Error: Order delete should only have affected one row. Instead, it affected %d", rowsAffected)
			return
		}
	} else {
		updateOrderQuery := fmt.Sprintf("UPDATE %s SET amountHave=%d, amountWant=%d WHERE hashedOrder='%x';", ao.pair.String(), exec.NewAmountHave, exec.NewAmountWant, exec.OrderID)
		var res sql.Result
		if res, err = tx.Exec(updateOrderQuery); err != nil {
			err = fmt.Errorf("Error updating order within tx for processorderexecution: %s", err)
			return
		}
		var rowsAffected int64
		if rowsAffected, err = res.RowsAffected(); err != nil {
			err = fmt.Errorf("Error while getting rows affected for process order execution: %s", err)
			return
		}
		if rowsAffected != 1 {
			logging.Errorf("Error: Order update should only have affected one row. Instead, it affected %d", rowsAffected)
		}
	}
	return
}
func (ao *SQLAuctionOrderbook) UpdateBookCancel(cancel *match.CancelledOrder) (err error) {
	var tx *sql.Tx
	if tx, err = ao.DBHandler.Begin(); err != nil {
		err = fmt.Errorf("Error when beginning transaction for UpdateBookCancel: %s", err)
		return
	}
	defer func() {
		if err != nil {
			tx.Rollback()
			err = fmt.Errorf("Error with UpdateBookCancel: \n%s", err)
			return
		}
		err = tx.Commit()
	}()
	if _, err = tx.Exec("USE " + ao.auctionOrderSchema + ";"); err != nil {
		err = fmt.Errorf("Error using auction schema for UpdateBookCancel: %s", err)
		return
	}
	deleteOrderQuery := fmt.Sprintf("DELETE FROM %s WHERE hashedOrder='%x';", ao.pair.String(), cancel.OrderID)
	var res sql.Result
	if res, err = tx.Exec(deleteOrderQuery); err != nil {
		err = fmt.Errorf("Error deleting order within tx for cancel: %s", err)
		return
	}
	var rowsAffected int64
	if rowsAffected, err = res.RowsAffected(); err != nil {
		err = fmt.Errorf("Error while getting rows affected for cancel: %s", err)
		return
	}
	if rowsAffected != 1 {
		err = fmt.Errorf("Error: Order cancel should only have affected one row. Instead, it affected %d", rowsAffected)
		return
	}
	return
}
func (ao *SQLAuctionOrderbook) UpdateBookPlace(auctionIDPair *match.AuctionOrderIDPair) (err error) {
	var tx *sql.Tx
	if tx, err = ao.DBHandler.Begin(); err != nil {
		err = fmt.Errorf("Error when beginning transaction for UpdateBookPlace: %s", err)
		return
	}
	defer func() {
		if err != nil {
			tx.Rollback()
			err = fmt.Errorf("Error for UpdateBookPlace: \n%s", err)
			return
		}
		err = tx.Commit()
	}()
	if _, err = tx.Exec("USE " + ao.auctionOrderSchema + ";"); err != nil {
		err = fmt.Errorf("Error using auction schema for UpdateBookPlace: %s", err)
		return
	}
	logging.Infof("Placing order in orderbook: \n%s", auctionIDPair.Order)
	insertOrderQuery := fmt.Sprintf("INSERT INTO %s VALUES ('%x', '%s', %f, %d, %d, '%x', '%x', '%x', '%x');", ao.pair.String(), auctionIDPair.Order.Pubkey, auctionIDPair.Order.Side, auctionIDPair.Price, auctionIDPair.Order.AmountHave, auctionIDPair.Order.AmountWant, auctionIDPair.Order.AuctionID, auctionIDPair.Order.Nonce, auctionIDPair.Order.Signature, auctionIDPair.OrderID)
	if _, err = tx.Exec(insertOrderQuery); err != nil {
		err = fmt.Errorf("Error placing order into db for UpdateBookPlace: %s", err)
		return
	}
	return
}