// NewQueryResultReaderForTablet creates a new QueryResultReader for // the provided tablet / sql query func NewQueryResultReaderForTablet(ts topo.Server, tabletAlias topo.TabletAlias, sql string) (*QueryResultReader, error) { tablet, err := ts.GetTablet(tabletAlias) if err != nil { return nil, err } endPoint, err := tablet.EndPoint() if err != nil { return nil, err } conn, err := tabletconn.GetDialer()(context.TODO(), *endPoint, tablet.Keyspace, tablet.Shard, 30*time.Second) if err != nil { return nil, err } sr, clientErrFn, err := conn.StreamExecute(context.TODO(), sql, make(map[string]interface{}), 0) if err != nil { return nil, err } // read the columns, or grab the error cols, ok := <-sr if !ok { return nil, fmt.Errorf("Cannot read Fields for query '%v': %v", sql, clientErrFn()) } return &QueryResultReader{ Output: sr, Fields: cols.Fields, conn: conn, clientErrFn: clientErrFn, }, nil }
// getConn reuses an existing connection if possible. Otherwise // it returns a connection which it will save for future reuse. // If it returns an error, retry will tell you if getConn can be retried. // If the context has a deadline and exceeded, it returns error and no-retry immediately. func (sdc *ShardConn) getConn(ctx context.Context) (conn tabletconn.TabletConn, endPoint topo.EndPoint, err error, retry bool) { sdc.mu.Lock() defer sdc.mu.Unlock() // fail-fast if deadline exceeded deadline, ok := ctx.Deadline() if ok { if time.Now().After(deadline) { return nil, topo.EndPoint{}, tabletconn.OperationalError("vttablet: deadline exceeded"), false } } if sdc.conn != nil { return sdc.conn, sdc.conn.EndPoint(), nil, false } endPoint, err = sdc.balancer.Get() if err != nil { return nil, topo.EndPoint{}, err, false } conn, err = tabletconn.GetDialer()(ctx, endPoint, sdc.keyspace, sdc.shard, sdc.timeout) if err != nil { sdc.balancer.MarkDown(endPoint.Uid, err.Error()) return nil, endPoint, err, true } sdc.conn = conn return sdc.conn, endPoint, nil, false }
func (conn *Conn) dial() (err error) { // build the endpoint in the right format host, port, err := netutil.SplitHostPort(conn.dbi.Host) if err != nil { return err } endPoint := topo.EndPoint{ Host: host, NamedPortMap: map[string]int{ "_vtocc": port, }, } // and dial tabletConn, err := tabletconn.GetDialer()(context.TODO(), endPoint, conn.keyspace(), conn.shard(), conn.timeout) if err != nil { return err } conn.tabletConn = tabletConn return }